accompanist
accompanist copied to clipboard
[Navigation Animation] You cannot access the NavBackStackEntry's ViewModels after the NavBackStackEntry is destroyed.
Description
If you have animations disabled on the device, have an AnimatedNavHost inside of another AnimatedNavHost, and that second AnimatedNavHost is inside of a Scaffold, and you attempt to navigate back with the back button, the exception from the title occurs. The "steps to reproduce" section has a list of requirements needed to reproduce this crash, and I have also created a minimum project (<80 lines) that will reproduce it. https://github.com/jasonctoms/NavigationAnimationCrash
I use these nested nav hosts to do navigation inside of a scaffold with a shared TopBar. The steps to reproduce here seem a little insane, but this crash occurs every time in automated tests.
In the sample project, you will notice that the behavior when closing the modal screen is different when you use the back button vs calling the same callback with a button (even when using a BackHandler composable).
Steps to reproduce
- Disable animations in Accessibility Settings
- Have an
AnimatedNavHostinside of Scaffold, with all of that inside of anotherAnimatedNavHost(image the second NavHost is part of a modal wizard to create a new item, for example) - Pass a lambda down from the main NavHost that will close the inner NavHost when pressing back.
- Navigate to a screen in the inner NavHost
- Use the back button on the device (or back gesture) to close the inner NavHost
Expected behavior The inner screen closes and you are back at your initial destination. You can see this happen, but then there is an immediate crash.
Additional context This does not happen if you remove the Scaffold or enable animations on the device.
See https://github.com/jasonctoms/NavigationAnimationCrash for a small project where this is reproduced (made from New Activity template with compose, with just accompanist navigation added as a dependency)
I have the same issue too
I am facing the same problem. Versions what I am using accompanist 0.27.1, lifecycle v2.5.1 and composeBom 2022.11.00 (Compose 1.3.1) on Android 13. In previous version I don't have this issue. I can reproduce it when I in click on navigation Up button very fast after navigating to some screen (probably when animation is running yet.)
Do you have any workaround or solution?
i have the same issue for months already
Same here, I'm on latest alphas:
compose - 1.4.0-alpha03 accompanist - 0.29.0-alpha
On non-animated compose navigation everything works as expected.
When you nest two NavHost the way you have done here, they are completely independent and not aware of one another. So this crash is caused because your are popping the NavBackStackEntry and destroying the lifecycle that is the host of your inner NavHost, but the Scaffold has not yet been disposed, so it is likely attempting to recompose again with an already DESTROYED Lifecycle.
Does the problem still occur if you are not using a Modal sheet? I would guess that intercepting back with a BackHandler() might mean that it is not getting the dismiss signal it might be expecting so it won't get disposed when expected.
Not sure there are any signals available for Navigation that would make this work as implemented. The destination had its entry popped and its Lifecycle is correctly DESTROYED. Trying to compose another NavHost after that will crash. Even if we added a blocker to avoid the inner NavHost recomposing when DESTROYED, the UI would likely be thrown away too quick ended up in a blank before the new destination came back.
Popping both of the NavControllers at the same time might be enough of a workaround to avoid the crash? The inner NavController would have an empty back stack when it gets recomposed and might just no-op while the outer NavHost returns to the screen.
I'm having the same problem but in my case the crash occurs when the back button of a modal screen is clicked in fast succession, so popBackStack() is probably called twice or more. I have the following setup:
AnimatedNavHost
- MainScreen
- Scaffold
- AnimatedNavHost
- [Screens with shared bottom navigation]
- ModalScreen
- Scaffold
- [Content]
What is the strategy to prevent multiple popBackStack() calls? Just disable the back button (or any button that calls popBackStack()) after the first click?
I created two extension functions on NavController which ensure that I don't navigate back beyond a certain point. It seems to have fixed my crashes.
/**
* Calls [NavController.popBackStack] unless there is no previous back stack entry which means
* we're already at the root entry.
*/
fun NavController.popToRootAtMost() {
if (previousBackStackEntry == null) return
popBackStack()
}
/**
* Calls [NavController.popBackStack] if the current route is [route], else does nothing.
*/
fun NavController.popToAncestorOf(route: String) {
if (currentDestination?.route != route) return
popBackStack()
}
This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days.
Going to close this as infeasible for the reasons stated in https://github.com/google/accompanist/issues/1396#issuecomment-1386381567