Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Compose cannot access Hilt View Model after popping the navigation stack

I have this code in my app:

@Composable
fun LogInScreen(
    navController: NavHostController,
) {
    val backStackEntry = remember(navController.currentBackStackEntry) {
        navController.getBackStackEntry(MainAppNavOptions.AuthScreen.name)
    }
    val viewModel: AuthViewModel = hiltViewModel(backStackEntry)
    ...
    LaunchedEffect(key1 = viewModel.isUserSignInState.value){
        if (viewModel.isUserSignInState.value){
            navController.navigate(MainAppNavOptions.MainScreen.name){
                popUpTo(MainAppNavOptions.MainScreen.name){
                    inclusive = true
                }
            }
        }
    }
    ...
}

So here I’m getting my shared view model for the auth screens, and then I’m navigating to my main screen after successful login.

But it seems like to LogInScreen function runs again, and because I’m popping the back stack, it cant get the view model and throws an error:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

    java.lang.IllegalArgumentException: No destination with route AuthScreen is on the NavController's back stack. The current destination is Destination(0x532bad98) route=HomeScreen
at androidx.navigation.NavController.getBackStackEntry(NavController.kt:2440)
at com.elog.findnchat.ui.auth.login.LogInScreenKt.LogInScreen(LogInScreen.kt:55)
at com.elog.findnchat.ui.navigation.NavGraphKt$authScreens$1$2.invoke(navGraph.kt:204)
at com.elog.findnchat.ui.navigation.NavGraphKt$authScreens$1$2.invoke(navGraph.kt:203)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:138)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
at androidx.navigation.compose.NavHostKt$NavHost$14$1.invoke(NavHost.kt:320)
at androidx.navigation.compose.NavHostKt$NavHost$14$1.invoke(NavHost.kt:318)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:108)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228)
at androidx.compose.runtime.saveable.SaveableStateHolderImpl.SaveableStateProvider(SaveableStateHolder.kt:84)
at androidx.navigation.compose.NavBackStackEntryProviderKt.SaveableStateProvider(NavBackStackEntryProvider.kt:65)
at androidx.navigation.compose.NavBackStackEntryProviderKt.access$SaveableStateProvider(NavBackStackEntryProvider.kt:1)
at androidx.navigation.compose.NavBackStackEntryProviderKt$LocalOwnersProvider$1.invoke(NavBackStackEntryProvider.kt:52)
at androidx.navigation.compose.NavBackStackEntryProviderKt$LocalOwnersProvider$1.invoke(NavBackStackEntryProvider.kt:51)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:108)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228)
at androidx.navigation.compose.NavBackStackEntryProviderKt.LocalOwnersProvider(NavBackStackEntryProvider.kt:47)
at androidx.navigation.compose.NavHostKt$NavHost$14.invoke(NavHost.kt:318)
at androidx.navigation.compose.NavHostKt$NavHost$14.invoke(NavHost.kt:302)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:138)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
at androidx.compose.animation.AnimatedContentKt$AnimatedContent$6$1$4.invoke(AnimatedContent.kt:780)
at androidx.compose.animation.AnimatedContentKt$AnimatedContent$6$1$4.invoke(AnimatedContent.kt:769)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:117)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
at androidx.compose.animation.AnimatedVisibilityKt.AnimatedEnterExitImpl(AnimatedVisibility.kt:941)
at androidx.compose.animation.AnimatedVisibilityKt.AnimatedVisibility(AnimatedVisibility.kt:607)
at androidx.compose.animation.AnimatedContentKt$AnimatedContent$6$1.invoke(AnimatedContent.kt:757)
at androidx.compose.animation.AnimatedContentKt$AnimatedContent$6$1.invoke(AnimatedContent.kt:740)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:108)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
at androidx.compose.animation.AnimatedContentKt.AnimatedContent(AnimatedContent.kt:794)
at androidx.navigation.compose.NavHostKt.NavHost(NavHost.kt:280)
at androidx.navigation.compose.NavHostKt$NavHost$16.invoke(Unknown Source:27)
at androidx.navigation.compose.NavHostKt$NavHost$16.invoke(Unknown Source:10)
at androidx.compose.runtime.RecomposeScopeImpl.compose(RecomposeScopeImpl.kt:169)
at androidx.compose.runtime.ComposerImpl.recomposeToGroupEnd(Composer.kt:2468)
2023-08-28 19:15:51.868  7084-7084  AndroidRuntime          com.elog.findnchat                   E      at androidx.compose.runtime.ComposerImpl.skipCurrentGroup(Composer.kt:2737)
at androidx.compose.runtime.ComposerImpl.doCompose(Composer.kt:3352)
at androidx.compose.runtime.ComposerImpl.recompose$runtime_release(Composer.kt:3303)
at androidx.compose.runtime.CompositionImpl.recompose(Composition.kt:781)
at androidx.compose.runtime.Recomposer.performRecompose(Recomposer.kt:1097)
at androidx.compose.runtime.Recomposer.access$performRecompose(Recomposer.kt:124)
at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$1.invoke(Recomposer.kt:569)
at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$1.invoke(Recomposer.kt:537)
at androidx.compose.ui.platform.AndroidUiFrameClock$withFrameNanos$2$callback$1.doFrame(AndroidUiFrameClock.android.kt:41)
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)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:970)
at android.view.Choreographer.doCallbacks(Choreographer.java:796)
at android.view.Choreographer.doFrame(Choreographer.java:727)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:957)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7698)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [androidx.compose.runtime.PausableMonotonicFrameClock@9e62ed5, androidx.compose.ui.platform.MotionDurationScaleImpl@70506ea, StandaloneCoroutine{Cancelling}@83b6ddb, AndroidUiDispatcher@f28b078]

Some notes:

  • yes, it’s working if I’m not popping the stack, but it’s neccery
  • I’ve tried adding if (viewModel.isUserSignInState.value) return and it’s working, but I dont think that it’s the best way…

>Solution :

remember(navController.currentBackStackEntry) is the wrong key to be using, since that field is immediately invalidated as soon as you pop.

You should be using the navBackStackEntry that is given to you by the composable function when building your graph – this ensures that recompositions due to the exiting transition still retain their state even while the pop is happening.

By using the right key, the getBackStackEntry call won’t be called again while you are exiting, allowing to you continue to use that data while your screen exits.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading