Jonathan
09/19/2024, 6:43 PMSeri
09/19/2024, 7:35 PMJonathan
09/19/2024, 7:35 PMJonathan
09/19/2024, 7:35 PM@Composable
inline fun <reified T: ViewModel> NavBackStackEntry.sharedViewModel(
navController: NavController,
): T {
val parentGraph = destination.parent ?: return koinNavViewModel()
val parentViewModelStoreOwner = remember(this) {
navController.getViewModelStoreOwner(parentGraph.id)
}
return koinNavViewModel(viewModelStoreOwner = parentViewModelStoreOwner)
}
Jonathan
09/19/2024, 7:36 PMIan Lake
09/19/2024, 7:38 PMJonathan
09/19/2024, 7:39 PMnavController.navigate(
route = screen,
navOptions = if (clearBackStack) {
navOptions {
// Pop up to the start destination of the graph to
// avoid building up a large stack of destinations
// on the back stack as users select items
popUpTo(navController.graph.findStartDestination().id) {
saveState = saveBackStackState
}
// Avoid multiple copies of the same destination when
// reselecting the same item
launchSingleTop = true
// Restore state when reselecting a previously selected item
restoreState = saveBackStackState
}
} else null)
Jonathan
09/19/2024, 7:40 PMIan Lake
09/19/2024, 7:42 PMJonathan
09/19/2024, 7:43 PMnavController.navigate(route = screen)
Ian Lake
09/19/2024, 7:44 PMJonathan
09/19/2024, 7:46 PMIan Lake
09/19/2024, 7:47 PMpopUpTo
without any of the rest of thatJonathan
09/19/2024, 7:50 PMfun navigateTo(
screen: AWScreen,
) = navController.navigate(
route = screen,
navOptions = navOptions {
// Pop up to the start destination of the graph to
// avoid building up a large stack of destinations
// on the back stack as users select items
popUpTo(navController.graph.findStartDestination().id)
})
Jonathan
09/19/2024, 7:56 PMIan Lake
09/19/2024, 10:57 PMNavHost(route = Root, startDestination = OnboardingGraph) {
navigation<OnBoardingGraph>(startDestination = Login) {
composable<Login>()
composable<Register>()
Composable<Success>()
}
navigation<HomeGraph>() {
composable<Home>()
}
}
So when you navigate to a destination, the navigation graphs are on the back stack too, so you start out at:
Root -> OnboardingGraph -> Login
If you navigate(Register)
, your back stack becomes
Root -> OnboardingGraph -> Login -> Register
Similarly when you `navigate(Success)`:
Root -> OnBoardingGraph -> Login -> Register -> Success
You'll note that here the Login
and Register
screens are still on the back stack, despite you being on Success
. You could have avoided that by using
navigate(Success) {
popUpTo<Login> { inclusive = true }
}
Which means you want to pop up to Login
and use inclusive = true
to also pop Login
, which would instead mean your back stack looks like
Root -> OnboardingGraph -> Success
And then if you wanted to move to Home
and pop the entire OnboardingGraph
off at once, you could use
navigate(Home) {
popUpTo<OnboardingGraph> { inclusive = true }
}
which would put you at:
Root -> HomeGraph -> Home
Ian Lake
09/19/2024, 10:59 PMnavController.getBackStackEntry
(which is what you really should be using instead of getViewModelStoreOwner
- keep in mind that a NavBackStackEntry
implements ViewModelStoreowner
, so both APIs give you the same object back, but only getBackStackEntry
supports the type safe APIs), what you are doing is finding the entry on the back stackIan Lake
09/19/2024, 11:00 PMnavController.getBackStackEntry<OnboardingGraph>()
if you want to store your ViewModel in the OnboardingGraph
Ian Lake
09/19/2024, 11:01 PMIan Lake
09/19/2024, 11:02 PMOnboardingGraph
, navigating from one to another sibling will keep the entire graph around. If you pop the entire graph / every destination in that graph off the back stack, then yep, you will lose the graph tooJonathan
09/20/2024, 1:40 PMnavController.navigate(…)
and slightly changing dependency on my “shared” VM. The final destination that required the previous sibling screens to no longer be navigable, didn’t actually need use the “shared” VM, I’ve given it its own VM and it works correctly. @Ian Lake Thank you for your explanation. This will help me in the future.