Using Compose Navigation, after pop, certain viewm...
# compose
l
Using Compose Navigation, after pop, certain viewmodel is keep at the viewmodelstore. Is it normal behavior? Because I thought that it should be removed 🤔
i
ViewModels tied to popped destinations should be cleared. If you're seeing something else, please file a bug with a sample project https://issuetracker.google.com/issues/new?component=409828&template=1093757
l
Maybe I am missing something. But I have the following logic:
Copy code
composable(HOME) {...} //will navigate to A

composable(A) { // Will navigate to B
  val qrViewModel = viewModel(
      viewModelStoreOwner = backStackEntry.rememberParentEntry(navHostController   = navHostController),
      factory = ...
      ), modelClass = QrViewModel::class.java
  )
}

composable(B) { // Will navigate to C
  val qrViewModel = viewModel(
      viewModelStoreOwner = backStackEntry.rememberParentEntry(navHostController   = navHostController),
      factory = ...
      ), modelClass = QrViewModel::class.java
  )
}

composable(C) { // Will pop
  val qrViewModel = viewModel(
      viewModelStoreOwner = backStackEntry.rememberParentEntry(navHostController   = navHostController),
      factory = ...
      ), modelClass = QrViewModel::class.java
  )
  // Stuff...
  navHostController.popBackStack(HOME, false)

}
After the popBackStack at C, I end up at HOME. But when entering again at A, the viewmodel is retrieved from its previous state, instead of recreating it
i
What is
backStackEntry.rememberParentEntry(navHostController   = navHostController)
doing
l
Copy code
fun NavBackStackEntry.rememberParentEntry(navHostController: NavHostController): NavBackStackEntry {
    val parentId = this.destination.parent!!.id
    return remember(this) { navHostController.getBackStackEntry(parentId) }
}
i
Well yeah, then you are storing the ViewModel on the parent, not on the individual destinations. None of your code is popping your parent navigation graph
Did you mean to wrap A, B, and C, inside a nested navigation graph?
l
Yeah, I see the problem. A, B, and C are neither inside a nested navigation graph
So, the views (a,b, and c) are storing the viewmodel at Home, right?
i
No, they're stored at the navigation graph level. If you aren't using any nested navigation graphs at all, that means they are global to the entire NavHost
(that's why
NavHost
takes an optional
route
parameter - if you want to name that top level navigation graph)
l
Perfect
Now I see the problem
thanks
j
Wow, Ian, thanks for that route parameter description. I’m working on updating my app’s navigation to use nested nav graphs and I have some cases where I need to pop up to that top level graph and wasn’t sure the “right” way to do so. Seems like I can name the top level graph with this and then pop up to it, though. That’s great.
s
I also found the
route
parameter confusing in general. I wonder if that’s just me not being familiar with the concept, or if there is some room for this explanation in the documentation. Or if I am completely missing some part of the docs that explains this already of course.
j
Yeah, it says that it is the route for the graph in the kdoc, but I think the information I was missing was that there is an implicit top level NavGraph which is always at the very beginning of your backstack. I found it by logging out the backstack and saw that it’s ID was 0 so started to pop up to that ID, but that’s relying on an implementation detail of the default ID value which I didn’t like. This allows me to name it to ensure I can reference it consistently across future releases
The top level nav graph totally makes sense, but I didn’t realize that the nav graphs are added in the backstack along with the other destinations which then makes it clear that this top level nav graph would be there
i
Yep, we actually specifically call that out in the shared ViewModel documentation for the Navigation Component: https://developer.android.com/guide/navigation/navigation-programmatic#share_ui-related_data_between_destinations_with_viewmodel A big focus for this year is in combining the existing Navigation Component docs with Compose, making it more clear what the common parts that apply to any implementation of the Navigation Component and what is Navigation with Fragments specific and what is Navigation Compose specific (turns out, 90% is all the same set of shared concepts)
j
Ah, nice! The main documentation I read was the “Navigating with Compose” one so adding that statement about the nav graphs back stack entries there in the Nested Navigation section would help, I think. If I came across the other page you linked, I would’ve probably stopped reading when I saw the Fragment references since we don’t have fragments in our app at all, but I’ll remember to not do that in the future for stuff like this where the underlying components are the same.
i
Yeah, that one page is never going to summarize the 24 pages of Navigation pages enough to cover it all; it is much closer to a getting started guide than a comprehensive guide
Having the rest of the pages being Compose first is the goal though 🙂
jetpack compose 1