如果提供的匹配器无法满足您的使用情形,您可以
扩展 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 } }