Jetpack Compose导航图间数据传递失败,求解决方案
Jetpack Compose导航图间数据传递失败问题
我需要在Jetpack Compose的导航图之间传递数据,以下是我的实现代码:
const val vitaminGraphRoutePattern = "vitamin_graph" const val vitaminRoute = "vitamin_route" fun NavController.navigateToVitamin( managerToken: String, managerId: Int, navOptions: NavOptions? = null ) { Log.d("vitamin", "navigateToVitamin: $managerToken, $managerId") this.navigate( route = "$vitaminGraphRoutePattern/$vitaminRoute?$MANAGER_TOKEN=$managerToken&$MANAGER_ID=$managerId", navOptions ) } @OptIn(ExperimentalAnimationApi::class) fun NavGraphBuilder.vitaminGraph( nestedGraphs: NavGraphBuilder.() -> Unit ) { navigation( route = vitaminGraphRoutePattern, startDestination = vitaminRoute, ) { nestedGraphs() } } @OptIn(ExperimentalAnimationApi::class) fun NavGraphBuilder.vitaminScreen( moveToWelcomeSurvey: (surveyToken: String, answerData: QuestionAnswerData, managerToken: String, managerId: Int) -> Unit, moveToResult: (surveyToken: String, managerToken: String, managerId: Int) -> Unit ) { composable( route = "$vitaminRoute?" + "$MANAGER_TOKEN=${MANAGER_TOKEN}" + "&$MANAGER_ID=${MANAGER_ID}", arguments = listOf( navArgument(MANAGER_TOKEN) { type = NavType.StringType defaultValue = "no value" }, navArgument(MANAGER_ID) { type = NavType.IntType defaultValue = -1 } ) ) { backStackEntry -> VitaminRoute( moveToWelcomeSurvey = { surveyToken, answerData -> moveToWelcomeSurvey( surveyToken, answerData, backStackEntry.arguments?.getString(MANAGER_TOKEN) ?: "", backStackEntry.arguments?.getInt(MANAGER_ID) ?: -1 ) }, moveToResult = { surveyToken -> moveToResult( surveyToken, backStackEntry.arguments?.getString(MANAGER_TOKEN) ?: "", backStackEntry.arguments?.getInt(MANAGER_ID) ?: -1 ) } ) } }
我尝试了以下两种导航写法,但均未成功,也尝试修改vitaminGraph的查询参数,依然无效:
写法1:
this.navigate( route = "$vitaminGraphRoutePattern?$MANAGER_TOKEN=$managerToken&$MANAGER_ID=$managerId", navOptions )
写法2:
this.navigate( route = "$vitaminGraphRoutePattern/$vitaminRoute?$MANAGER_TOKEN=$managerToken&$MANAGER_ID=$managerId", navOptions )
请问该如何解决此问题?
问题分析与修复方案
核心问题在于导航图(navigation组件)无法直接持有查询参数,且目标页面的路由参数占位符格式错误,导致参数无法被正确解析传递。
1. 修正路由参数占位符错误
在vitaminScreen的composable路由定义中,你错误地将参数常量本身作为占位符值:
// 错误写法 route = "$vitaminRoute?" + "$MANAGER_TOKEN=${MANAGER_TOKEN}" + "&$MANAGER_ID=${MANAGER_ID}"
正确的参数占位符格式应为{参数名},这样导航组件才能识别并解析传递的参数值。
2. 正确传递参数到目标页面
导航图仅作为页面分组容器,参数需要直接传递到其起始目标页面(即vitaminRoute),导航图会自动跳转到起始页并携带参数。
修正后的完整代码
导航扩展函数
const val vitaminGraphRoutePattern = "vitamin_graph" const val vitaminRoute = "vitamin_route" const val MANAGER_TOKEN = "manager_token" const val MANAGER_ID = "manager_id" fun NavController.navigateToVitamin( managerToken: String, managerId: Int, navOptions: NavOptions? = null ) { Log.d("vitamin", "navigateToVitamin: $managerToken, $managerId") // 直接导航到vitaminRoute,携带参数,导航图自动处理起始页跳转 this.navigate( route = "$vitaminGraphRoutePattern/$vitaminRoute?$MANAGER_TOKEN=$managerToken&$MANAGER_ID=$managerId", navOptions ) }
导航图定义
@OptIn(ExperimentalAnimationApi::class) fun NavGraphBuilder.vitaminGraph( nestedGraphs: NavGraphBuilder.() -> Unit ) { navigation( route = vitaminGraphRoutePattern, startDestination = vitaminRoute, ) { nestedGraphs() } }
目标页面定义
@OptIn(ExperimentalAnimationApi::class) fun NavGraphBuilder.vitaminScreen( moveToWelcomeSurvey: (surveyToken: String, answerData: QuestionAnswerData, managerToken: String, managerId: Int) -> Unit, moveToResult: (surveyToken: String, managerToken: String, managerId: Int) -> Unit ) { composable( // 修正参数占位符格式 route = "$vitaminRoute?$MANAGER_TOKEN={$MANAGER_TOKEN}&$MANAGER_ID={$MANAGER_ID}", arguments = listOf( navArgument(MANAGER_TOKEN) { type = NavType.StringType defaultValue = "no value" }, navArgument(MANAGER_ID) { type = NavType.IntType defaultValue = -1 } ) ) { backStackEntry -> // 安全获取参数并复用 val token = backStackEntry.arguments?.getString(MANAGER_TOKEN) ?: "no value" val id = backStackEntry.arguments?.getInt(MANAGER_ID) ?: -1 VitaminRoute( moveToWelcomeSurvey = { surveyToken, answerData -> moveToWelcomeSurvey(surveyToken, answerData, token, id) }, moveToResult = { surveyToken -> moveToResult(surveyToken, token, id) } ) } }
额外优化建议
- 可以将参数设置为可空,避免使用默认值:
获取参数时直接用navArgument(MANAGER_TOKEN) { type = NavType.StringType nullable = true }backStackEntry.arguments?.getString(MANAGER_TOKEN)即可。 - 使用
Uri构建路由,避免字符串拼接错误:val route = Uri.parse("$vitaminGraphRoutePattern/$vitaminRoute") .buildUpon() .appendQueryParameter(MANAGER_TOKEN, managerToken) .appendQueryParameter(MANAGER_ID, managerId.toString()) .build() .toString() this.navigate(route, navOptions)
内容的提问来源于stack exchange,提问作者c-an
相关产品推荐
相关产品推荐

