Jetpack Compose. Navigation IllegalStateException

9
在快速切换目的地时(即底部导航:HomeScreen -> SettingsScreen -> HomeScreen),出现此异常。 导航实现按照文档示例应用程序中的示例。 也许这是Jetpack Compose的一个bug,因为我在互联网上没有找到类似的错误。

Getting exception

屏幕:

sealed class Screen(
val route: String,
@StringRes val title: Int,
@DrawableRes val icon: Int) {

object Home : Screen("HomeScreen", R.string.app_name, R.drawable.ic_baseline_chevron_right_24)
object Scanner : Screen("ScannerScreen", R.string.app_name, R.drawable.ic_baseline_chevron_right_24)
object Settings : Screen("SettingsScreen", R.string.app_name, R.drawable.ic_baseline_chevron_right_24)
}

底部导航:
@Composable
fun BottomNavigationBar(navController: NavController) {
    val items = listOf(
        Screen.Home,
        Screen.Scanner,
        Screen.Settings
    )
    BottomNavigation {
        val navBackStackEntry = navController.currentBackStackEntryAsState()
        val currentRoute = navBackStackEntry.value?.destination?.route
        items.forEach { item ->
            BottomNavigationItem(
                icon = { Icon(painter = painterResource(id = item.icon), contentDescription = item.title.toString()) },
                label = { Text(item.title.toString()) },
                selected = currentRoute == item.route,
                onClick = {
                    navController.navigate(item.route) {
                        navController.graph.startDestinationRoute?.let {
                            popUpTo(it) {
                                saveState = true
                            }
                        }
                        launchSingleTop = true
                        restoreState = true
                    }
                }
            )
        }
    }
}

导航:

@ExperimentalMaterialApi
@ExperimentalPermissionsApi
@Composable
fun MainScreen() {
    val navController = rememberNavController()
    Scaffold(
        bottomBar = { BottomNavigationBar(navController) }
    ) {
        Box(modifier = Modifier.padding(it)) {
            NavigationHost(navController)
        }
    }
}

@ExperimentalPermissionsApi
@ExperimentalMaterialApi
@Composable
fun NavigationHost(navController: NavHostController) {
    NavHost(
        navController = navController,
        startDestination = Screen.Scanner.route) {
        composable(Screen.Home.route) {
            HomeScreen()
        }
        composable(Screen.Scanner.route) {
            ScannerScreen()
        }
        composable(Screen.Settings.route) {
            SettingsScreen()
        }
    }
}

@Composable
fun HomeScreen() {
    // Body
}

@Composable
fun ScannerScreen() {
    // Body
}

@Composable
fun SettingsScreen() {
    // Body
}

日志:

java.lang.IllegalStateException: You cannot access the NavBackStackEntry's ViewModels until it is added to the NavController's back stack (i.e., the Lifecycle of the NavBackStackEntry reaches the CREATED state).
        at androidx.navigation.NavBackStackEntry.getViewModelStore(NavBackStackEntry.kt:174)
        at androidx.lifecycle.ViewModelProvider.<init>(ViewModelProvider.java:99)
        at androidx.lifecycle.viewmodel.compose.ViewModelKt.get(ViewModel.kt:82)
        at androidx.lifecycle.viewmodel.compose.ViewModelKt.viewModel(ViewModel.kt:72)
        at androidx.navigation.compose.NavBackStackEntryProviderKt.SaveableStateProvider(NavBackStackEntryProvider.kt:86)
        at androidx.navigation.compose.NavBackStackEntryProviderKt.access$SaveableStateProvider(NavBackStackEntryProvider.kt:1)
        at androidx.navigation.compose.NavBackStackEntryProviderKt$LocalOwnersProvider$1.invoke(NavBackStackEntryProvider.kt:51)
        at androidx.navigation.compose.NavBackStackEntryProviderKt$LocalOwnersProvider$1.invoke(NavBackStackEntryProvider.kt:50)
        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
        at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:215)
        at androidx.navigation.compose.NavBackStackEntryProviderKt.LocalOwnersProvider(NavBackStackEntryProvider.kt:46)
        at androidx.navigation.compose.NavHostKt$NavHost$3.invoke(NavHost.kt:132)
        at androidx.navigation.compose.NavHostKt$NavHost$3.invoke(NavHost.kt:131)
        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:116)
        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
        at androidx.compose.animation.CrossfadeKt$Crossfade$1$1.invoke(Crossfade.kt:74)
        at androidx.compose.animation.CrossfadeKt$Crossfade$1$1.invoke(Crossfade.kt:69)
        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
        at androidx.compose.animation.CrossfadeKt.Crossfade(Crossfade.kt:86)
        at androidx.navigation.compose.NavHostKt.NavHost(NavHost.kt:131)
        at androidx.navigation.compose.NavHostKt$NavHost$4.invoke(Unknown Source:13)
        at androidx.navigation.compose.NavHostKt$NavHost$4.invoke(Unknown Source:10)
        at androidx.compose.runtime.RecomposeScopeImpl.compose(RecomposeScopeImpl.kt:140)
        at androidx.compose.runtime.ComposerImpl.recomposeToGroupEnd(Composer.kt:2156)
        at androidx.compose.runtime.ComposerImpl.skipCurrentGroup(Composer.kt:2399)
        at androidx.compose.runtime.ComposerImpl$doCompose$2$5.invoke(Composer.kt:2580)
        at androidx.compose.runtime.ComposerImpl$doCompose$2$5.invoke(Composer.kt:2573)
        at androidx.compose.runtime.SnapshotStateKt.observeDerivedStateRecalculations(SnapshotState.kt:540)
        at androidx.compose.runtime.ComposerImpl.doCompose(Composer.kt:2566)
        at androidx.compose.runtime.ComposerImpl.recompose$runtime_release(Composer.kt:2542)
        at androidx.compose.runtime.CompositionImpl.recompose(Composition.kt:613)
        at androidx.compose.runtime.Recomposer.performRecompose(Recomposer.kt:764)
        at androidx.compose.runtime.Recomposer.access$performRecompose(Recomposer.kt:103)
        at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$2.invoke(Recomposer.kt:447)
        at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$2.invoke(Recomposer.kt:416)
        at androidx.compose.ui.platform.AndroidUiFrameClock$withFrameNanos$2$callback$1.doFrame(AndroidUiFrameClock.android.kt:34)
        at androidx.compose.ui.platform.AndroidUiDispatcher.performFrameDispatch(AndroidUiDispatcher.android.kt:109)
        at androidx.compose.ui.platform.AndroidUiDispatcher.access$performFrameDispatch(AndroidUiDispatcher.android.kt:41)
        at androidx.compose.ui.platform.AndroidUiDispatcher$dispatchCallback$1.doFrame(AndroidUiDispatcher.android.kt:69)
    2021-08-12 11:00:49.484 8306-8306/com.example.smartlumnew E/AndroidRuntime:     at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1008)
            at android.view.Choreographer.doCallbacks(Choreographer.java:809)
            at android.view.Choreographer.doFrame(Choreographer.java:740)
            at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:995)
            at android.os.Handler.handleCallback(Handler.java:938)
            at android.os.Handler.dispatchMessage(Handler.java:99)
            at android.os.Looper.loop(Looper.java:246)
            at android.app.ActivityThread.main(ActivityThread.java:8512)
            at java.lang.reflect.Method.invoke(Native Method)
            at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130)

2
删除了“restoreState = true”后,错误得到了解决。但是,我不知道这个决定是否正确。也许有更好的解决方案? - Tim Yumalin
1
组合导航目前处于 alpha 版本,因此可能会出现此类错误。我已经在问题跟踪器上找到了类似的问题报告:https://issuetracker.google.com/issues/195860509,https://issuetracker.google.com/issues/195687654。请关注它们,如果您发现它们不太相同,也可以将您的示例添加到其中之一。 - Phil Dukhov
1
如果有,编译器会突出显示哪一行? - Richard Onslow Roper
@MARSK,什么也没有。 - Tim Yumalin
通过降级到'2.4.0-alpha05',解决了这个问题。 - Andre Thiele
删除 restoreState = true 将导致不尝试访问 NavBackStackEntry,但缺点是 Fragment 的实例状态将会丢失。 - Martin Zeitler
2个回答

4

这个问题在当前版本中已得到解决,所以请更新至此版本并检查。

androidx.navigation:navigation-compose:2.4.0-alpha07


1

我通过降级到'androidx.navigation:navigation-compose:2.4.0-alpha05'来解决了问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接