Android Compose Navigation如何正确传递URL类型参数?
问题场景
我使用Jetpack Compose + Navigation开发Firebase邮箱链接认证功能:用户输入邮箱发起认证后,会收到包含认证链接的邮件,点击链接可通过Firebase Dynamic Link重新打开App。获取到emailLink后,尝试通过NavController的路由参数传递给Home页面,但出现参数被截断的问题。
出现问题的代码
动态链接处理代码
Firebase.dynamicLinks .getDynamicLink(intent) .addOnSuccessListener(this@MainActivity) { pendingDynamicLinkData: PendingDynamicLinkData? -> if (pendingDynamicLinkData != null) { val emailLink = intent?.data?.toString() if (emailLink != null && firebaseAuth.isSignInWithEmailLink(emailLink)) { intent = null navController.navigate("${Home.route}?emailLink={$emailLink}") } } } }
NavHost配置代码
NavHost( navController = navController, startDestination = Home.route, ) { composable( route = "${Home.route}?emailLink={emailLink}", arguments = listOf(navArgument("emailLink") { type = NavType.StringType nullable = true defaultValue = null }) ) { backStackEntry -> val emailLink = backStackEntry.arguments?.getString("emailLink") Log.i("TEST", "[sample] navigate - emailLink: $emailLink") HomeScreen( vm = hiltViewModel(), emailLink = emailLink ) } }
问题现象
原始完整的emailLink:
https://email-link-auth-sample-95a4a.firebaseapp.com/__/auth/action?apiKey=AIzaSyD2w6bRHiqEXaSx9W0N5Mq5obydIjRk_mw&mode=signIn&oobCode=dj8M6b4Rq6dwM81ziExyw_3-gXiExQY8FvHNAZsPDxMAAAGETZgg0w&continueUrl=https://emaillinkauthsample.page.link&lang=en
通过backStackEntry.arguments?.getString("emailLink")获取到的内容却被截断为:
{https://email-link-auth-sample-95a4a.firebaseapp.com/__/auth/action?apiKey=AIzaSyD2w6bRHiqEXaSx9W0N5Mq5obydIjRk_mw
本质原因是Compose Navigation基于URL系统设计,当参数包含&、?这类URL特殊字符时,会导致参数解析出错,出现截断。
已实现的解决方案(使用savedStateHandle)
修改后的动态链接处理代码
Firebase.dynamicLinks .getDynamicLink(intent) .addOnSuccessListener(this@MainActivity) { pendingDynamicLinkData: PendingDynamicLinkData? -> if (pendingDynamicLinkData != null) { val emailLink = intent?.data?.toString() if (emailLink != null && firebaseAuth.isSignInWithEmailLink(emailLink)) { intent = null // 注释掉原路由参数传递方式 // navController.navigate("${Home.route}?emailLink={$emailLink}") /** * 使用savedStateHandle传递参数 */ navController.currentBackStackEntry?.savedStateHandle?.apply { set("emailLink", emailLink) } navController.navigate(Home.route) } } } }
修改后的NavHost配置代码
NavHost( navController = navController, startDestination = Home.route, ) { composable( route = "${Home.route}?emailLink={emailLink}", arguments = listOf(navArgument("emailLink") { type = NavType.StringType nullable = true defaultValue = null }) ) { backStackEntry -> // 注释掉原参数获取方式 // val emailLink = backStackEntry.arguments?.getString("emailLink") /** * 从savedStateHandle获取参数 */ val emailLink = navController.previousBackStackEntry?.savedStateHandle?.get<String>("emailLink") HomeScreen( vm = hiltViewModel(), emailLink = emailLink ) } }
内容的提问来源于stack exchange,提问作者dev.farmer
相关产品推荐
相关产品推荐

