Nếu trình so khớp được cung cấp không đủ cho các trường hợp sử dụng của bạn, thì bạn có thể tạo trình so khớp riêng bằng cách mở rộng lớp DeepLinkMatcher.
Khi mở rộng DeepLinkMatcher<T, R>, bạn phải chỉ định hai đối số loại: loại khoá điều hướng đích (T : Any) và loại kết quả khớp (R : DeepLinkMatcher.MatchResult<T>). Nếu trình so khớp của bạn không cần thứ hạng kết quả tuỳ chỉnh hoặc siêu dữ liệu bổ sung, hãy sử dụng DeepLinkMatcher.MatchResult<T> làm đối số loại thứ hai.
Ví dụ: dưới đây là cách triển khai cơ bản của một TelDeepLinkMatcher hỗ trợ URI tel (chẳng hạn như tel:5550100). Vì URI tel không rõ ràng nên UriDeepLinkMatcher không hỗ trợ các URI này:
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)) } }
Xếp hạng MatchResult lớp tuỳ chỉnh
Nếu có cách phù hợp để so sánh kết quả so khớp từ trình so khớp tuỳ chỉnh, bạn nên mở rộng DeepLinkMatcher.MatchResult và ghi đè phương thức compareTo để xếp hạng kết quả.
Khi bạn tạo một lớp con MatchResult tuỳ chỉnh, hãy cập nhật nội dung khai báo lớp của trình so khớp để chỉ định lớp con đó làm tham số loại thứ hai R (chẳng hạn như class TelDeepLinkMatcher : DeepLinkMatcher<DialerKey, TelMatchResult>()).
Thao tác này cho phép phương thức gọi truy cập vào các thuộc tính kết quả tuỳ chỉnh mà không cần truyền kiểu dữ liệu xuống không được kiểm tra.
Ví dụ: để hỗ trợ so khớp mẫu ký tự đại diện trong TelDeepLinkMatcher, bạn có thể triển khai TelMatchResult để đảm bảo kết quả khớp chính xác có thứ hạng cao hơn kết quả khớp ký tự đại diện. Nếu trình so khớp được gói trong withBackStack, hãy huỷ gói WrappedMatchResult trước khi so sánh để mức độ ưu tiên được đánh giá dựa trên kết quả khớp cơ bản:
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 } }