You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jetpack Navigation无法匹配NavDeepLinkRequest目标路由问题求助

解决Jetpack Navigation传递复杂参数跳转报错问题

问题重现

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 13:45:31