提供されているマッチャーがユースケースに十分でない場合は、
DeepLinkMatcherクラスを拡張して独自のマッチャーを作成できます。
DeepLinkMatcher<T, R> を拡張する場合は、宛先ナビゲーション キーのタイプ(T : Any)と一致結果のタイプ(R : DeepLinkMatcher.MatchResult<T>)の 2 つのタイプ引数を指定する必要があります。マッチャーでカスタム結果のランキングや追加のメタデータが必要ない場合は、2 番目のタイプ引数として DeepLinkMatcher.MatchResult<T> を使用します。
たとえば、TelDeepLinkMatcher の基本的な実装は次のようになります。tel URI(tel:5550100 など)をサポートします。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 サブクラスを作成する場合は、マッチャーのクラス
宣言を更新して、そのサブクラスを 2 番目のタイプ パラメータ 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 } }