提供されているマッチャーがユースケースに十分でない場合は、DeepLinkMatcher クラスを拡張して独自のマッチャーを作成できます。
DeepLinkMatcher<T, R> を拡張する場合は、2 つの型引数(デスティネーション ナビゲーション キーの型(T : Any)と一致結果の型(R : DeepLinkMatcher.MatchResult<T>))を指定する必要があります。マッチャーでカスタム結果ランキングや追加のメタデータが必要ない場合は、2 番目の型引数として 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 サブクラスを作成するときは、マッチャーのクラス宣言を更新して、そのサブクラスを 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 } }