Clament John
10/20/2021, 8:57 AMsetContent {
val navController = rememberNavController()
NavHost(navController = navController, startDestination = "home") {
navigation(startDestination = "username", route = "login") {
// FIXME: I get an error here
val viewModel: LoginViewModel = viewModel()
composable("username") { ... }
composable("password") { ... }
composable("registration") { ... }
}
}
}
I get an error
@Composable invocations can only happen from the context of a @Composable functionNeed • The viewmodel should only be active in the NavGraph Scope. • When I go to a different route and come back I should initialize a new viewmodel (this is why I'm calling it in the NavGraph) Almost similar solution 1. Answer by [Philip Dukhov](https://stackoverflow.com/users/3585796/philip-dukhov) for the question [How to share a viewmodel between two or more Jetpack composables inside a Compose NavGraph?](https://stackoverflow.com/a/68857871/5698740) a. But in this approach the viewmodel stays in the scope of the activity that launched it and so is never garbage collected.
Csaba Kozák
10/20/2021, 9:04 AMWhen I go to a different route and come back I should initialize a new viewmodel (this is why I’m calling it in the NavGraph)What do you mean by this? Can you give us an example?
Clament John
10/20/2021, 9:07 AMProfile
.
But when we come to compose. We don't have an activity instead we have nav graphs. So we will add a route profile
and have a bunch of fragments below it as "sub routes"Csaba Kozák
10/20/2021, 9:10 AMNavHost
es well?Clament John
10/20/2021, 9:10 AMClament John
10/20/2021, 9:12 AMCsaba Kozák
10/20/2021, 9:16 AMval loginBackStackEntry = remember { navController.getBackStackEntry("login") }
val loginViewModel: LoginViewModel = viewModel(loginBackStackEntry)
Clament John
10/20/2021, 9:24 AMBackStackEntry
for the current navGraph login
2. This backStackEntry, according to the navigation docs is scoped to a navigation graph login
3. And since we have a scope for the navGraph we can have our viewmodel
in that scope and share it among all the members of the scope.
4. We are using remember
because we are getting the scope as a state so that the composable can be recomposed when the scope changes?
Am I right?Csaba Kozák
10/20/2021, 2:50 PMIan Lake
10/21/2021, 5:50 AMremember
part is particularly important when you consider what is happening when the system back button is pressed: your screen and that whole navigation graph may no longer be on the back stack (since the back button just popped them), but your destination is still on screen and being recomposed (since it is animating out). If you leave off the remember
, then you've lost your reference to that NavBackStackEntry
Ian Lake
10/21/2021, 5:52 AMClament John
10/21/2021, 9:34 AMremember
, instead, you are getting the viewmodel directly from the navController.
And in your last comments you say
it is still valid to keep that reference up until the screen finishes it's animation
So adding
remember
is just a good measure and not needed?
Basically my question is
• Why didn't you use remember in your answerIan Lake
10/21/2021, 12:45 PMremember
. That answer was from before there was any animation support at allClament John
10/21/2021, 12:48 PMremember
Ian Lake
10/21/2021, 12:50 PMviewModel()
Ian Lake
10/21/2021, 12:51 PMIan Lake
10/24/2021, 2:24 PMremember
Clament John
10/24/2021, 4:36 PM