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