Jetpack Compose底部导航点击触发空指针异常,导航功能失效
嘿,我一眼就发现问题所在啦!你遇到的NullPointerException,核心原因是你在底部导航组件里重新创建了一个独立的NavController实例,没有和页面的NavHost共用同一个控制器。
问题分析
在你的App函数里,明明已经创建了val navController = rememberNavController()并传给了AppNavHost,但在AppBottomNavigation组件中,你又重新写了val navController = rememberNavController()——这就导致底部导航用的是一个全新的、没有关联任何NavHost的控制器。调用navigate方法时,这个孤立的控制器找不到对应的导航图(NavGraph),自然就抛出空指针异常了。
修复方案
只需要让底部导航和NavHost共用同一个NavController实例就行,步骤如下:
修改
AppBottomNavigation,添加navController参数
删掉组件内部创建的NavController,改为接收父组件传进来的实例:@Composable fun AppBottomNavigation( modifier: Modifier = Modifier, navController: NavHostController // 新增参数,接收外部传入的控制器 ) { // 移除这里的 val navController = rememberNavController() BottomNavigation(modifier) { BottomNavigationItem( icon = { Icon( imageVector = Icons.Default.Home, contentDescription = null ) }, label = { Text(stringResource(R.string.home1)) }, selected = true, onClick = { navController.navigate("home1") } // 使用传入的控制器 ) BottomNavigationItem( icon = { Icon( imageVector = Icons.Default.AccountCircle, contentDescription = null ) }, label = { Text(stringResource(R.string.home2)) }, selected = false, onClick = { navController.navigate("home2") } // 使用传入的控制器 ) } }在
App函数中传递navController给底部导航
把App里创建好的navController传给AppBottomNavigation:@Composable fun App() { val navController = rememberNavController() Scaffold( bottomBar = { AppBottomNavigation(navController = navController) } // 传递控制器 ) { padding -> AppNavHost( Modifier.padding(padding), navController, "home1" ) } }优化
AppNavHost,避免默认创建控制器
为了防止后续误用,建议去掉AppNavHost中navController的默认值,强制要求传入外部的控制器:@Composable fun AppNavHost( modifier: Modifier = Modifier, navController: NavHostController, // 去掉默认值,必须传入 startDestination: String = "home2" ) { NavHost( modifier = modifier, navController = navController, startDestination = startDestination ) { composable(route = "home1") { ListHotelScreen() } composable(route = "home2") { ListBookingScreen() } } }
这样修改后,整个App就只有一个NavController实例,底部导航和NavHost共用它,点击底部导航项时就能正确匹配路由节点,空指针问题也就解决啦!
备注:内容来源于stack exchange,提问作者RCamel

