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:
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:
if (viewModel.isUserSignInState.value) return
and it's working, but I dont think that it's the best way...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.