Jetpack Navigation无法匹配NavDeepLinkRequest目标路由问题求助
问题重现
使用Jetpack Navigation跳转页面时,传递序列化后的JSON字符串作为参数,触发如下错误:
java.lang.IllegalArgumentException: Navigation destination that matches request NavDeepLinkRequest{ uri=android-app://androidx.navigation/hero_details_screen/{"attackType":"MELEE",...} } cannot be found in the navigation graph
错误原因
直接将包含{}、"、空格等特殊字符的JSON字符串拼接到路由中,会破坏Navigation的路由解析规则——这些特殊字符会被识别为路由路径的一部分,而非参数内容,导致无法匹配预先定义的hero_details_screen/{item}路由。
解决方案
方案1:URL编码/解码参数
通过对JSON字符串进行URL编码,避免特殊字符干扰路由解析,接收参数时再解码还原内容。
修改后的代码:
sealed class NavigationScreen(val route: String) { object HeroesPageScreen: NavigationScreen("hero_information_screen") object HeroDetails: NavigationScreen("hero_details_screen") fun withArgs(vararg args: String): String { return buildString { append(route) args.forEach { arg -> append("/$arg") } } } } @ExperimentalFoundationApi @Composable fun NavigationHero() { val navController = rememberNavController() NavHost(navController = navController, startDestination = NavigationScreen.HeroesPageScreen.route) { composable(route = NavigationScreen.HeroesPageScreen.route) { HeroesPageScreen(navController = navController) } composable(route = NavigationScreen.HeroDetails.route + "/{item}", arguments = listOf( navArgument("item") { type = NavType.StringType nullable = true }) ){ navBackStackEntry -> navBackStackEntry.arguments?.getString("item")?.let { encodedJson -> // 解码参数还原JSON val json = URLDecoder.decode(encodedJson, "UTF-8") val item = Gson().fromJson(json, HeroInfoData::class.java) HeroDetails(data = item) } } } } @Composable fun HeroCardItem(data: HeroInfoData, navController: NavController) { Card( modifier = Modifier .clickable { val itemJson = Gson().toJson(data) // 对JSON字符串进行URL编码 val encodedJson = URLEncoder.encode(itemJson, "UTF-8") navController.navigate(NavigationScreen.HeroDetails.route + "/$encodedJson") } .padding(5.dp) .fillMaxSize(), elevation = 5.dp, shape = RoundedCornerShape(5.dp) ) { // Card内容实现 } }
方案2:使用Safe Args传递复杂对象(推荐)
Safe Args是Jetpack Navigation官方提供的类型安全参数传递方案,可彻底避免手动拼接路由的错误,更适合传递复杂对象。
步骤1:配置Safe Args插件
在项目根目录的build.gradle中添加插件依赖:
plugins { id "androidx.navigation.safeargs.kotlin" version "2.7.7" apply false }
在app模块的build.gradle中应用插件:
plugins { id "androidx.navigation.safeargs.kotlin" }
步骤2:修改导航与跳转逻辑
编译后插件会自动生成类型安全的参数类和跳转方法,修改代码如下:
@ExperimentalFoundationApi @Composable fun NavigationHero() { val navController = rememberNavController() NavHost(navController = navController, startDestination = NavigationScreen.HeroesPageScreen.route) { composable(route = NavigationScreen.HeroesPageScreen.route) { HeroesPageScreen(navController = navController) } composable( route = NavigationScreen.HeroDetails.route, arguments = listOf( navArgument("item") { type = NavType.StringType nullable = true } ) ){ navBackStackEntry -> // 使用自动生成的Args类解析参数 val args = HeroDetailsArgs.fromNavArgs(navBackStackEntry) args.item?.let { json -> val item = Gson().fromJson(json, HeroInfoData::class.java) HeroDetails(data = item) } } } } @Composable fun HeroCardItem(data: HeroInfoData, navController: NavController) { Card( modifier = Modifier .clickable { val itemJson = Gson().toJson(data) // 使用自动生成的跳转方法 navController.navigate(HeroDetailsDirections.actionToHeroDetails(itemJson)) } .padding(5.dp) .fillMaxSize(), elevation = 5.dp, shape = RoundedCornerShape(5.dp) ) { // Card内容实现 } }
内容的提问来源于stack exchange,提问作者aewisshhh
相关产品推荐
相关产品推荐

