如果提供的比對器不符合您的用途,您可以擴充 DeepLinkMatcher 類別,自行建立比對器。
擴充 DeepLinkMatcher<T, R> 時,您必須指定兩個類型引數:目的地導覽鍵類型 (T : Any) 和比對結果類型 (R : DeepLinkMatcher.MatchResult<T>)。如果比對器不需要自訂結果排名或額外中繼資料,請使用 DeepLinkMatcher.MatchResult<T> 做為第二個類型引數。
舉例來說,以下是支援 tel URI (例如 tel:5550100) 的 TelDeepLinkMatcher 基本實作。由於 tel URI 不透明,因此 UriDeepLinkMatcher 不支援:
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 } }