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

Jetpack Compose嵌套导航图触发ViewModelStore需在setGraph前设置异常如何解决

问题根因

你错误地将全局根NavHostController同时绑定了两个独立的NavHost实例:根导航图的NavHost已经完成setGraph初始化,你在AppScaffold内部再次使用同一个NavController创建第二个NavHost时,重复触发setGraph调用,就会抛出ViewModelStore should be set before setGraph call异常。


修复方案

按照嵌套导航图的规范调整结构,移除AppScaffold内部的冗余NavHost,将底部导航页面直接定义在bottomBar子导航图中,具体修改如下:

1. 修改AppScaffold.kt

移除内部的NavHost,仅保留Scaffold框架,将内容区域作为参数传入:

@Composable
fun AppScaffold(
    navController: NavHostController,
    content: @Composable (PaddingValues) -> Unit
) {
    val scaffoldState = rememberScaffoldState()
    Scaffold(
        bottomBar = {
            BottomBar(mainNavController = navController)
        },
        scaffoldState = scaffoldState,
        content = content
    )
}

2. 重写BottomBarNavGraph.kt

直接将三个底部导航页面定义在子导航图中,外层包裹AppScaffold:

fun NavGraphBuilder.bottomBarNavGraph(
    navController: NavHostController,
    userViewModel: UserViewModel
) {
    navigation(
        startDestination = NavigationScreen.EmergencyCallScreen.route,
        route = BOTTOM_BAR_GRAPH_ROUTE
    ) {
        composable(NavigationScreen.EmergencyCallScreen.route) {
            AppScaffold(navController = navController) { padding ->
                EmergencyCallScreen(
                    modifier = Modifier.padding(padding),
                    navController = navController,
                    loginViewModel = userViewModel
                )
            }
        }
        composable(NavigationScreen.ChatScreen.route) { 
            AppScaffold(navController = navController) { padding ->
                ChatScreen(modifier = Modifier.padding(padding)) 
            }
        }
        composable(NavigationScreen.SettingsScreen.route) {
            AppScaffold(navController = navController) { padding ->
                SettingsScreen(
                    modifier = Modifier.padding(padding),
                    navController = navController,
                    loginViewModel = userViewModel
                )
            }
        }
    }
}

3. 调整跳转逻辑

  • 登录/注册页跳转到指定底部页面:直接调用navController.navigate(NavigationScreen.你需要跳转的页面.route)即可
  • 底部页面跳回登录页:调用以下代码清除底部导航栈,避免回退回到应用内部页面:
navController.navigate(LOGIN_GRAPH_ROUTE) {
    popUpTo(BOTTOM_BAR_GRAPH_ROUTE) {
        inclusive = true
    }
}
  • 根NavHost的起始目的地可根据登录状态动态设置:未登录时设置为LOGIN_GRAPH_ROUTE,已登录时设置为BOTTOM_BAR_GRAPH_ROUTE即可。

4. 可选优化

你可以删除Screen类中冗余的AppScaffold路由配置,本次调整后不会再用到该路由。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 21:54:06