如何在Jetpack Compose中实现带参数页面导航?解决跳转空指针异常
Jetpack Compose 页面导航与参数传递实现方案
一、先解决 NullPointerException 问题
空指针的核心原因是NavController 未正确初始化或未关联到 NavHost,你当前的代码缺少导航组件的核心配置,按以下步骤修复:
1. 添加导航依赖
在 build.gradle(Module level) 中添加匹配你 Compose 版本的导航依赖:
dependencies { implementation "androidx.navigation:navigation-compose:2.7.7" }
2. 正确初始化 NavHost
修改 MainActivity,创建 NavController 并关联 NavHost,定义所有页面的路由:
// MainActivity.kt class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { YourAppTheme { val navController = rememberNavController() // 初始化NavController NavHost( navController = navController, startDestination = "loginPage1" // 设置初始页面 ) { composable("loginPage1") { LoginPage1(navController = navController) // 传递NavController } composable("onboardingPage1") { OnboardingPage1() // 目标页面,后续添加参数传递逻辑 } } } } } }
3. 修复 LoginPage1 的跳转逻辑
现在可以安全使用 navController 跳转,不会触发空指针:
// LoginPage1.kt @Composable fun LoginPage1(navController: NavController) { Button( onClick = { navController.navigate("onboardingPage1") }, shape = MaterialTheme.shapes.medium, colors = ButtonDefaults.buttonColors(orange) ) { Text("跳转到引导页") } }
二、页面间传递参数
下面提供两种常用的参数传递方式:
方式1:路由路径传参(适合简单参数,如字符串、数字)
1. 修改路由定义,添加参数占位符
// 在NavHost的composable中修改目标页面路由 composable( route = "onboardingPage1/{userId}/{userName}", // 用{}定义参数占位符 arguments = listOf( navArgument("userId") { type = NavType.StringType }, navArgument("userName") { type = NavType.StringType } ) ) { backStackEntry -> // 从backStackEntry中获取参数 val userId = backStackEntry.arguments?.getString("userId") ?: "" val userName = backStackEntry.arguments?.getString("userName") ?: "" OnboardingPage1(userId = userId, userName = userName) }
2. 发起跳转时携带参数
// LoginPage1的按钮点击事件 onClick = { val userId = "12345" val userName = "Nirali" navController.navigate("onboardingPage1/$userId/$userName") }
3. 目标页面接收参数
// OnboardingPage1.kt @Composable fun OnboardingPage1(userId: String, userName: String) { Column( modifier = Modifier.fillMaxSize(), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center ) { Text("用户ID:$userId") Text("用户名:$userName") } }
方式2:Bundle传参(适合复杂参数或可选参数)
1. 定义路由时声明可选参数
composable( route = "onboardingPage1", arguments = listOf( navArgument("userInfo") { type = NavType.ParcelableType(UserInfo::class.java) nullable = true // 标记为可选参数 } ) ) { backStackEntry -> val userInfo = backStackEntry.arguments?.getParcelable<UserInfo>("userInfo") OnboardingPage1(userInfo = userInfo) }
2. 创建可序列化的参数类
// 实现Parcelable接口,支持跨页面传递 @Parcelize data class UserInfo(val userId: String, val userName: String, val age: Int) : Parcelable
3. 跳转时携带参数
// LoginPage1的按钮点击事件 onClick = { val userInfo = UserInfo("12345", "Nirali", 25) navController.navigate( "onboardingPage1", navOptions { arguments = bundleOf("userInfo" to userInfo) } ) }
4. 目标页面接收参数
@Composable fun OnboardingPage1(userInfo: UserInfo?) { userInfo?.let { info -> Column( modifier = Modifier.fillMaxSize(), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center ) { Text("用户ID:${info.userId}") Text("用户名:${info.userName}") Text("年龄:${info.age}") } } }
三、常见注意事项
- 确保所有页面路由在 NavHost 中都已定义,否则会引发路由未找到异常
- 参数类型要和路由中声明的
NavType一致,避免类型转换错误 - 可选参数要设置
nullable = true,并在接收时做非空判断
内容的提问来源于stack exchange,提问作者Nirali Pandya
相关产品推荐
相关产品推荐

