I'm sometimes getting an IllegalStateException whe...
# compose
c
I'm sometimes getting an IllegalStateException when rapidly navigating between items on my BottomNavigation. The exception is:
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).
My BottomNavigation code is:
Copy code
@Composable
fun BottomNavBar(navController: NavHostController, bottomNavItems: List<AppScreen>) {
  BottomNavigation {
    val currentRoute = navController.currentDestination?.route
    bottomNavItems.forEach { screen ->
      val selected = currentRoute == screen.route
      BottomNavigationItem(
        icon = { Icon(painter = painterResource(id = screen.iconId), contentDescription = null) },
        label = { Text(screen.name) },
        selected = selected,
        onClick = {
          if (!selected) {
            navController.navigate(screen.route) {
              popUpTo(navController.graph.findStartDestination().id)
              launchSingleTop = true
            }
          }
        }
      )
    }
  }
}
It seems to be due to the combination of calling popUpTo() and setting launchSingleTop. If either or both of those lines are removed, the problem goes away. Any ideas what I can do to fix this? Is the problem here, or maybe due to something I'm doing in one of my screens?
Full stacktrace here if that is helpful:
Copy code
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-09 15:04:38.033 32198-32198/jacketcontrol E/AndroidRuntime:     at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1152)
        at android.view.Choreographer.doCallbacks(Choreographer.java:977)
        at android.view.Choreographer.doFrame(Choreographer.java:885)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1139)
        at android.os.Handler.handleCallback(Handler.java:883)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7682)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:516)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)
t
Which version of navigation compose are you using?
c
2.4.0-alpha06
t
Are you using nested navigation? If so It might be this bug https://issuetracker.google.com/issues/194313238
c
Thanks. I'm not using nested nav, but looks like it is a related issue all the same
One of my screens is somewhat "heavier" than the others and likely takes a bit longer to render. That's the one that generally seems to trigger it if I switch rapidly between screens. Maybe I'll try disabling animation (as per the previous person's question 😄) and see if that helps
t
Usually it’s because the state of the backstack entry during animation. It might worth a try
c
Yep that seems to have solved it... thanks for the pointer! I think I'll just add a comment on the issue and live with the bug for now with the assumption it'll be fixed soon/eventually.
🙌 1
t
Good idea!
c
i
What are you passing into
viewModel()
? That's where the exception is being sent from. It is way, way, way easier for us to solve issues if you include a runnable project in your issue
c
I can try and create a small repro project but will take me a while. What exactly do you mean by "passing into
viewModel()
" though? I have a single ViewModel that is passed in to my setContent{} composable inside onCreate(), and passed on from there to each "screen"
s
Im facing the same after updating nav to alpha06, compose 1.0.1 & kotlin 1.5.21. I didnt face it on nav alpha04. Not using nested graphs, idk if its cause of nav or hilt viewmodel. Code in case someone wants to see: https://github.com/ShivamKumarJha/supaflix/blob/main/app/src/main/java/com/shivamkumarjha/supaflix/ui/dashboard/NavigationContent.kt#L20
c
OK I've added a project to the issue that demonstrates the problem. I'm not using Hilt so doubt it is that
👍 1
s
Also i observed that the compose state is not being saved, on reselecting bottom tab paging data from viewmodel was reloaded
133 Views