首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >JetpackCompose导航嵌套图导致"ViewModelStore应在setGraph调用之前设置“异常

JetpackCompose导航嵌套图导致"ViewModelStore应在setGraph调用之前设置“异常
EN

Stack Overflow用户
提问于 2021-10-27 12:06:46
回答 1查看 1.1K关注 0票数 5

我正在尝试将Jetpack Compose导航应用到我的应用程序中。

我的屏幕:登录/注册屏幕和底部导航栏屏幕(通话、聊天、设置)。

我已经发现最好的方法是使用嵌套图。

但我一直收到ViewModelStore should be set before setGraph call异常。然而,我不认为这是正确的例外。

我的导航已经是最新版本了。可能我的嵌套图逻辑不正确。

要求:我希望能够从登录或注册屏幕导航到任何BottomBar屏幕&反向

代码语言:javascript
运行
复制
@Composable
fun SetupNavGraph(
    navController: NavHostController,
    userViewModel: UserViewModel
) {
    NavHost(
        navController = navController,
        startDestination = BOTTOM_BAR_GRAPH_ROUTE,
        route = ROOT_GRAPH_ROUTE
    ) {
        loginNavGraph(navController = navController, userViewModel)
        bottomBarNavGraph(navController = navController, userViewModel)
    }
}

NavGraph.kt

代码语言:javascript
运行
复制
fun NavGraphBuilder.loginNavGraph(
    navController: NavHostController,
    userViewModel: UserViewModel
) {
    navigation(
        startDestination = Screen.LoginScreen.route,
        route = LOGIN_GRAPH_ROUTE
    ) {
        composable(
            route = Screen.LoginScreen.route,
            content = {
                LoginScreen(
                    navController = navController,
                    loginViewModel = userViewModel
                )
            })
        composable(
            route = Screen.RegisterScreen.route,
            content = {
                RegisterScreen(
                    navController = navController,
                    loginViewModel = userViewModel
                )
            })
    }
}

LoginNavGraph.kt

代码语言:javascript
运行
复制
fun NavGraphBuilder.bottomBarNavGraph(
    navController: NavHostController,
    userViewModel: UserViewModel
) {
    navigation(
        startDestination = Screen.AppScaffold.route,
        route = BOTTOM_BAR_GRAPH_ROUTE
    ) {
        composable(
            route = Screen.AppScaffold.route,
            content = {
                AppScaffold(
                    navController = navController,
                    userViewModel = userViewModel
                )
            })
    }
}

BottomBarNavGraph.kt

代码语言:javascript
运行
复制
@Composable
fun AppScaffold(
    navController: NavHostController,
    userViewModel: UserViewModel
) {
    val scaffoldState = rememberScaffoldState()

    Scaffold(

        bottomBar = {
            BottomBar(mainNavController = navController)
        },
        scaffoldState = scaffoldState,

        ) {

        NavHost(
            navController = navController,
            startDestination = NavigationScreen.EmergencyCallScreen.route
        ) {
            composable(NavigationScreen.EmergencyCallScreen.route) {
                EmergencyCallScreen(
                    navController = navController,
                    loginViewModel = userViewModel
                )
            }
            composable(NavigationScreen.ChatScreen.route) { ChatScreen() }
            composable(NavigationScreen.SettingsScreen.route) {
                SettingsScreen(
                    navController = navController,
                    loginViewModel = userViewModel
                )
            }
        }
    }
}

AppScaffold.kt

代码语言:javascript
运行
复制
@Composable
fun BottomBar(mainNavController: NavHostController) {

    val items = listOf(
        NavigationScreen.EmergencyCallScreen,
        NavigationScreen.ChatScreen,
        NavigationScreen.SettingsScreen,
    )

    BottomNavigation(
        elevation = 5.dp,
    ) {
        val navBackStackEntry by mainNavController.currentBackStackEntryAsState()
        val currentRoute = navBackStackEntry?.destination?.route
        items.map {
            BottomNavigationItem(
                icon = {
                    Icon(
                        painter = painterResource(id = it.icon),
                        contentDescription = it.title
                    )
                },
                label = {
                    Text(
                        text = it.title
                    )
                },
                selected = currentRoute == it.route,
                selectedContentColor = Color.White,
                unselectedContentColor = Color.White.copy(alpha = 0.4f),
                onClick = {
                    mainNavController.navigate(it.route) {
                        mainNavController.graph.startDestinationRoute?.let { route ->
                            popUpTo(route) {
                                saveState = true
                            }
                        }
                        restoreState = true
                        launchSingleTop = true
                    }
                },

                )
        }

    }
}

BottomBar.kt

代码语言:javascript
运行
复制
const val ROOT_GRAPH_ROUTE = "root"
const val LOGIN_GRAPH_ROUTE = "login_register"
const val BOTTOM_BAR_GRAPH_ROUTE = "bottom_bar"

sealed class Screen(val route: String) {
    object LoginScreen : Screen("login_screen")
    object RegisterScreen : Screen("register_screen")
    object AppScaffold : Screen("app_scaffold")

}

Screen.kt

代码语言:javascript
运行
复制
sealed class NavigationScreen(val route: String, val title: String, @DrawableRes val icon: Int) {
    object EmergencyCallScreen : NavigationScreen(
        route = "emergency_call_screen",
        title = "Emergency Call",
        icon = R.drawable.ic_phone
    )

    object ChatScreen :
        NavigationScreen(
            route = "chat_screen",
            title = "Chat",
            icon = R.drawable.ic_chat)

    object SettingsScreen : NavigationScreen(
        route = "settings_screen",
        title = "Settings",
        icon = R.drawable.ic_settings
    )
}

NavigationScreen.kt

EN

回答 1

Stack Overflow用户

发布于 2021-11-13 16:14:06

不允许嵌套NavHost。这会导致在setGraph调用异常之前设置ViewModelStore。通常,docs显示的底部nav在NavHost之外。推荐的方法是一个单一的NavHost,你可以根据你所在的目的地隐藏和显示你的底部导航。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69738397

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档