如果提供的比對器無法滿足您的用途,您可以擴充 DeepLinkMatcher 類別,自行建立比對器。
擴充 DeepLinkMatcher<T, R> 時,您必須指定兩個型別引數:目的地導覽鍵型別 (T : Any) 和比對結果型別 (R : DeepLinkMatcher.MatchResult<T>)。如果比對器不需要自訂結果排名或額外中繼資料,請使用 DeepLinkMatcher.MatchResult<T> 做為第二個型別引數。
舉例來說,以下是支援 tel URI (例如 tel:5550100) 的 TelDeepLinkMatcher 基本實作方式。由於 tel URI 不透明,因此 UriDeepLinkMatcher 不支援這些 URI:
class TelDeepLinkMatcher : DeepLinkMatcher<DialerKey, DeepLinkMatcher.MatchResult<DialerKey>>() { override fun matchRequest(request: DeepLinkRequest): MatchResult<DialerKey>? { val uri = request.uri ?: return null if (uri.scheme != "tel") return null // Note: schemeSpecificPart is only available on Android val phoneNumber = uri.schemeSpecificPart ?: return null return MatchResult(DialerKey(phoneNumber = phoneNumber)) } }
為自訂 MatchResult 類別排名
如果可以有意義地比較自訂比對器的比對結果,您應擴充 DeepLinkMatcher.MatchResult 並覆寫 compareTo 方法,為結果排序。
建立自訂 MatchResult 子類別時,請更新比對工具的類別宣告,將該子類別指定為第二個型別參數 R (例如 class TelDeepLinkMatcher : DeepLinkMatcher<DialerKey, TelMatchResult>())。這樣一來,呼叫端就能存取自訂結果屬性,而不必進行未檢查的向下轉換。
舉例來說,如要在 TelDeepLinkMatcher 中支援萬用字元模式比對,您可以實作 TelMatchResult,確保完全比對的排名高於萬用字元比對。如果比對器包裝在 withBackStack 中,請先取消包裝 WrappedMatchResult 再進行比較,這樣系統就會根據基礎比對結果評估優先順序:
class TelMatchResult( key: DialerKey, val isExactMatch: Boolean, val patternLength: Int ) : DeepLinkMatcher.MatchResult<DialerKey>(key) { override fun compareTo(other: DeepLinkMatcher.MatchResult<DialerKey>): Int { // Unwrap if the other result is wrapped in a BackStackMatchResult or custom WrappedMatchResult val target = if (other is WrappedMatchResult<*>) other.matchResult else other if (target !is TelMatchResult) { // Determine precedence relative to other MatchResult types (e.g. UriMatchResult) return 1 } // An exact match wins over a wildcard/prefix match if (isExactMatch && !target.isExactMatch) return 1 if (!isExactMatch && target.isExactMatch) return -1 // The more specific (longer) pattern wins (e.g., tel:1800* versus tel:*) val lengthDiff = this.patternLength - target.patternLength if (lengthDiff != 0) { return lengthDiff } return 0 } }