دستورالعمل DeepLinkMatcher سفارشی
این دستورالعمل نشان میدهد که چگونه بااستفاده از موارد اضافی درخواست سفارشی و Kotlinx Serialization، یک DeepLinkMatcher سفارشی در «پیمایش ۳» ایجاد کنید.
روش کار
این دستور غذا از دو فعالیت تشکیل شده است:
CustomDeepLinkMatcherActivity: ورودی کاربر را میپذیرد، نمونهHomeKeyرا به JSON تبدیل میکند، آن را ازطریقRequestExtrasKeyبهIntentاضافی پیوست میکند، وMainActivityرا راهاندازی میکند.-
MainActivity: یکDeepLinkRequest(intent)میسازد، آن را باJsonDeepLinkMatcherارزیابی میکند،HomeKeyرا رمزگشایی میکند، و آن را بهعنوان مسیر شروع درNavDisplayتنظیم میکند.
مفاهیم کلیدی
-
سفارشی
RequestExtrasKey:JsonDeepLinkMatcherKeyکلید اضافی سفارشیای را تعریف میکند کهRequestExtrasKey<String>را برای ذخیره و خواندن ایمن پایهبارهای JSON سریالیشده درDeepLinkRequest.extrasپیادهسازی میکند. -
سفارشی
DeepLinkMatcher:JsonDeepLinkMatcher<T>DeepLinkMatcher<T, MatchResult<T>>را گسترش میدهد وmatchRequest(request)را پیادهسازی میکند تاrequest.extras[JsonDeepLinkMatcherKey]را استخراج کند و آن را بااستفاده از Kotlinx Serialization بهNavKeyبا نوع قوی رمزگشایی کند.
package com.example.nav3recipes.deeplink.usecases.matcher import android.content.Intent import android.os.Bundle import android.util.Log import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.material3.ElevatedButton import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.Text import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.dropUnlessResumed import androidx.navigation3.runtime.NavKey import androidx.navigation3.runtime.deeplink.DeepLinkMatcher import androidx.navigation3.runtime.deeplink.DeepLinkRequest import androidx.navigation3.runtime.deeplink.RequestExtrasKey import com.example.nav3recipes.common.deeplink.EntryScreen import com.example.nav3recipes.ui.setEdgeToEdgeConfig import kotlinx.serialization.KSerializer import kotlinx.serialization.SerializationException import kotlinx.serialization.json.Json class CustomDeepLinkMatcherActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { setEdgeToEdgeConfig() super.onCreate(savedInstanceState) setContent { EntryScreen { Column( verticalArrangement = Arrangement.spacedBy(32.dp), horizontalAlignment = Alignment.CenterHorizontally, ) { var text by remember { mutableStateOf("") } OutlinedTextField( placeholder = { Text("Your name...", color = Color.Black.copy(alpha = 0.5f)) }, value = text, singleLine = true, onValueChange = { text = it }, ) ElevatedButton( onClick = dropUnlessResumed { val intent = Intent( this@CustomDeepLinkMatcherActivity, MainActivity::class.java ) val json = Json.encodeToString(HomeKey.serializer(), HomeKey(text)) intent.putExtra(JsonDeepLinkMatcherKey.toString(), json) startActivity(intent) } ) { Text("Sign up") } } } } } } internal data object JsonDeepLinkMatcherKey: RequestExtrasKey<String> internal class JsonDeepLinkMatcher<T: NavKey>(val serializer: KSerializer<T>): DeepLinkMatcher<T, DeepLinkMatcher.MatchResult<T>>() { override fun matchRequest(request: DeepLinkRequest): MatchResult<T>? { val json = request.extras[JsonDeepLinkMatcherKey] ?: return null return try { val result = Json.decodeFromString(serializer, json) MatchResult(result) } catch (e: SerializationException) { Log.v("DeepLinkMatcher", "Failed to decode json", e) return null } } }
package com.example.nav3recipes.deeplink.usecases.matcher import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.navigation3.runtime.NavBackStack import androidx.navigation3.runtime.NavKey import androidx.navigation3.runtime.deeplink.DeepLinkRequest import androidx.navigation3.runtime.deeplink.invoke import androidx.navigation3.runtime.entryProvider import androidx.navigation3.runtime.rememberNavBackStack import androidx.navigation3.ui.NavDisplay import com.example.nav3recipes.common.deeplink.EntryScreen import com.example.nav3recipes.common.deeplink.TextContent import com.example.nav3recipes.ui.setEdgeToEdgeConfig import kotlinx.serialization.Serializable import kotlinx.serialization.serializer @Serializable internal data class HomeKey(val name: String): NavKey @Serializable internal object FallbackKey: NavKey class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { setEdgeToEdgeConfig() super.onCreate(savedInstanceState) val request = DeepLinkRequest(intent) val deepLinkMatcher = createJsonDeepLinkMatcher<HomeKey>() val matchResult = deepLinkMatcher.match(request) val key = matchResult?.key ?: FallbackKey setContent { val backStack: NavBackStack<NavKey> = rememberNavBackStack(key) NavDisplay( backStack = backStack, onBack = backStack::removeLastOrNull, entryProvider = entryProvider { entry<HomeKey> { key -> EntryScreen("Welcome") { TextContent(key.name) } } entry<FallbackKey> { key -> EntryScreen("Fallback Key") { TextContent( "Failed to deep link - DeepLinkRequest " + "did not match with any DeepLinkMatcher" ) } } } ) } } } // Optional JsonDeepLinkMatcher factory function that automatically captures KSerializer for T. private inline fun <reified T : NavKey> createJsonDeepLinkMatcher(): JsonDeepLinkMatcher<T> { val serializer = serializer<T>() return JsonDeepLinkMatcher(serializer) }