julioromano
12/07/2022, 10:19 AMjulioromano
12/07/2022, 10:19 AMViewModel but navigation actions must be invoked on the NavController object which is inside the composition in the Activity.
Since the lifecycle of the Activity is shorter than that of the ViewModel we can’t pass references to functions such as NavController.popUpToWelcomeScreen() from the Activity to the ViewModel (besides the potential of memory leaks, we’ll loose the reference to the function any time the activity is recreated).
How to properly encapsulate conditional navigation using the pattern proposed in the video?Pablichjenkov
12/07/2022, 2:44 PM@Composable
fun LogoutScreen(accountViewModel: AccountViewModel) {
val loginStatus by accountViewModel.loginStatus.collectAsState()
when(loginStatus) {
LogIn -> { paintLogoutUI() }
LogOut -> { navController.navigate("WelcomePage") }
}
}
You don’t pass a reference from anywhere to the ViewModel, so the ViewModel invoke/callback later on, instead invert the flow. You request execution to the ViewModel and listen for the result of the execution. The ViewModel doesn;t know about its client, doesn’t call functions in its clientsIan Lake
12/07/2022, 4:18 PMColton Idle
12/07/2022, 6:35 PMjulioromano
12/12/2022, 3:21 PMNavHost would allow its state to be hoisted so that we could directly manipulate it?
After all isn’t Jetpack Compose about manipulating hoisted state to trigger updates to the UI instead of having to manually change a `View`’s internal state by calling its setters?
Every time I do a navController.navigate() I feel like I’m doing something like textView.setText() .Ian Lake
12/12/2022, 4:06 PMnavigate is just how you update the state of the NavController, just like how you call open or close on a DrawerStateIan Lake
12/12/2022, 4:10 PMPablichjenkov
12/12/2022, 7:13 PMIan Lake
12/12/2022, 8:09 PMPablichjenkov
12/12/2022, 9:07 PMjulioromano
12/13/2022, 7:52 AMThere are quite a few composition state holders that can’t be hoisted out of composition safety though - ScrollState looks like it can be hoisted, but any attempt to change the state from a ViewModel actually just crashes..This opens the pandora’s box of architectural opinions: Should a given composable’s state be manageable by the ViewModel/BusinessLogic or should it be exclusive to the UI layer? I don’t think there’s a definitive answer for this. Take
ScrollState for instance, in most cases most people would be okay with it being exclusive to the UI layer, so that the business logic can be agnostic about it and the UI will transparently take care of restoring the scroll position of a list.
But things change as soon as the business requirements say that the list must be programmatically scrolled to a certain position whenever a certain business operation has been completed. In this case we would like for the ScrollState to be hoisted to our ViewModel/BusinessLogic to better control it.
So maybe it boils down to a matter of balancing “how complicated is it to make a certain state work out of the composition” with “how useful is it to actually be able to hoist a certain state out of the composition”.
IMHO (just my 2 cents that are worth much less than that 🙂 ) for ScrollState the usefulness would be minimal, but for NavHost I’d say quite the opposite.Colton Idle
12/13/2022, 9:08 AMNavController is already the hoisted state of the NavHost.🤯 @Manuel Vivo i guess this also goes hand in hand with how we talked about the fact that you can't actually hoist the state of a bottom sheet into a ViewModelis just how you update the state of the NavController, just like how you callnavigateoropenon acloseDrawerState
Manuel Vivo
12/13/2022, 11:47 AMjulioromano
12/13/2022, 12:25 PMNavHost falls in that caveat’s topic though, navController.navigate() is not suspending.Pablichjenkov
12/13/2022, 2:03 PM