맞춤 DeepLinkMatcher 레시피
이 레시피는 맞춤 요청 추가 기능과 Kotlinx 직렬화를 사용하여 Navigation 3에서 맞춤 DeepLinkMatcher를 만드는 방법을 보여줍니다.
작동 방식
이 레시피는 두 가지 활동으로 구성됩니다.
CustomDeepLinkMatcherActivity: 사용자 입력을 수락하고,HomeKey인스턴스를 JSON으로 직렬화하고,RequestExtrasKey를 통해Intent추가 기능에 연결하고,MainActivity를 실행합니다.MainActivity:DeepLinkRequest(intent)를 구성하고,JsonDeepLinkMatcher로 평가하고,HomeKey를 디코딩하고,NavDisplay에서 시작 경로로 설정합니다.
주요 개념
-
맞춤
RequestExtrasKey:JsonDeepLinkMatcherKey는DeepLinkRequest.extras에서 직렬화된 JSON 페이로드를 유형 안전 방식으로 저장하고 읽기 위해RequestExtrasKey<String>을 구현하는 맞춤 추가 키를 정의합니다. -
맞춤
DeepLinkMatcher:JsonDeepLinkMatcher<T>는DeepLinkMatcher<T, MatchResult<T>>를 확장하고matchRequest(request)를 구현하여request.extras[JsonDeepLinkMatcherKey]를 추출하고 Kotlinx 직렬화를 사용하여 강력한 유형의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) }