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

Jetpack Compose点击底部导航项应用崩溃问题求助

问题原因分析

你遇到的崩溃核心原因是:在BottomNavigation组件内部新建了一个NavHostController,但这个控制器从未和任何NavHost绑定(即没有设置导航图graph),当点击导航项尝试访问navController.graph时,就会触发You must call setGraph() before calling getGraph()的异常。

简单说就是:底部导航用的控制器和导航图用的控制器是两个完全独立的实例,前者没有任何导航配置,自然无法执行跳转逻辑。


修复方案

我们需要让底部导航和导航图共享同一个NavHostController,同时修复选中状态的错误判断逻辑,具体修改如下:

1. 重构导航图组件,接收外部控制器

将NavigationGraph改为接收外部传入的NavHostController,不再内部创建:

@Composable
fun NavigationGraph(navController: NavHostController) {
    NavHost(
        navController = navController, 
        startDestination = BottomNavItem.Home.screen_route
    ){
        composable(BottomNavItem.Home.screen_route) { HomeScreen() }
        composable(BottomNavItem.Call.screen_route) { CallScreen() }
        composable(BottomNavItem.Profile.screen_route) { ProfileScreen() }
        composable(BottomNavItem.Favorite.screen_route) { FavoriteScreen() }
    }
}

2. 在DashboardScreen中共享控制器

创建一个统一的NavHostController,同时传递给底部导航和导航图:

@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun DashboardScreen(navController: NavHostController) {
    // 创建底部导航专用的共享控制器
    val bottomNavController = rememberNavController()
    
    Scaffold(
        topBar = { CustomToolbarScreen(navController = navController, title = "Dashboard", false) }
    ) { innerPadding ->
        Column(
            modifier = Modifier.padding(innerPadding),
            verticalArrangement = Arrangement.Center,
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            Scaffold (
                bottomBar = {
                    BottomAppBar {
                        // 传递共享控制器给底部导航
                        BottomNavigation(navController = bottomNavController)
                    }
                }
            ) { scaffoldPadding ->
                Column(modifier = Modifier.padding(scaffoldPadding)) {
                    // 传递同一个控制器给导航图
                    NavigationGraph(navController = bottomNavController)
                }
            }
        }
    }
}

3. 修复底部导航组件,移除无效控制器

删掉BottomNavigation内部创建的NavHostController,改用传入的实例,并修复选中状态判断:

@Composable
fun BottomNavigation(navController: NavHostController) {
    val items = listOf(
        BottomNavItem.Home,
        BottomNavItem.Call,
        BottomNavItem.Profile,
        BottomNavItem.Favorite
    )
    val navBackStackEntry by navController.currentBackStackEntryAsState()
    val currentDestination = navBackStackEntry?.destination

    NavigationBar {
        items.forEach { item ->
            AddItem(
                screen = item,
                currentDestination = currentDestination,
                navController = navController
            )
        }
    }
}

@Composable
fun RowScope.AddItem(
    screen: BottomNavItem,
    currentDestination: NavDestination?,
    navController: NavHostController
) {
    // 用当前路由匹配判断是否选中,替换之前错误的类型匹配
    val isSelected = currentDestination?.hierarchy?.any { it.route == screen.screen_route } == true

    NavigationBarItem(
        label = { Text(text = screen.title, fontSize = 9.sp) },
        icon = { Icon(imageVector = screen.icon, contentDescription = screen.title) },
        selected = isSelected,
        alwaysShowLabel = true,
        onClick = {
            navController.navigate(screen.screen_route) {
                navController.graph.findStartDestination().route?.let { startRoute ->
                    popUpTo(startRoute) { saveState = true }
                }
                launchSingleTop = true
                restoreState = true
            }
        },
        colors = NavigationBarItemDefaults.colors(),
        modifier = Modifier.background(colorPrimary)
    )
}

关键修改点说明
  • 共享控制器:确保底部导航和导航图使用同一个NavHostController实例,避免出现无配置的控制器。
  • 修复选中判断:删除了无效的selectedTab状态,改用导航控制器的当前路由来判断选中状态,逻辑更可靠且符合Jetpack Navigation的设计规范。
  • 移除冗余代码:删掉了BottomNavigation内部无用的NavHostController创建逻辑,以及注释掉的错误跳转代码。

内容的提问来源于stack exchange,提问作者Rahul Rokade

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 21:19:55