Say you're building a new app with compose that wi...
# compose
r
Say you're building a new app with compose that will have lots of screens, and many of the screens will handle a fair number of network interactions and business logic. It seems like the preference in a pure compose app is to not use fragments at all. Does that mean a single activity app where I have a ViewModel for every screen that's tied to that single Activity's lifecycle? Are there any potential downsides to having many long-lived ViewModels?
v
The ViewModels don’t have to be tied to the activity. You can have a viewModel scoped to a composable. For example,
navigation
can scope a viewModel to a backStackEntry
val viewModel = hiltNavGraphViewModel()
edit: val viewModel = viewModel()
or viewModel(factory = HiltViewModelFactory(LocalContext.current, navBackStackEntry))
a
What if not using hilt?
i
Any call to
viewModel()
within a
NavHost
composable
will scope it to that individual screen (it doesn't matter what factory you use)
r
awesome, thanks!
g
Would you do something like this then?
Copy code
NavHost(navController, startDestination = Screen.LaunchScreen.route) {
        composable(Screen.LoadingScreen.route) { LoadingScreen() }
        composable(Screen.LaunchScreen.route) {
            val playersViewModel by viewModels<PlayersViewModel>()
            LaunchScreen(playersViewModel)
        }
    }
i
You'd use
val playersViewModel = viewModel<PlayersViewModel>()
in Compose land: https://developer.android.com/jetpack/compose/interop#viewmodel
g
Thanks @Ian Lake!
i
But yes, that would correctly scope the
PlayersViewModel
instance to only the
LaunchScreen
destination
f
What about the factories for the assisted inject, they all need to be injected into the activity then passed to the composables?
g
@FunkyMuse I've got this working:
Copy code
navController = rememberNavController()
    NavHost(navController, startDestination = Screen.LaunchScreen.route) {
        composable(Screen.LoadingScreen.route) { LoadingScreen() }
        composable(Screen.LaunchScreen.route) {
            val playersViewModel = viewModel<PlayersViewModel>(
                factory = PlayersViewModelFactory(
                    PlayersRepository()
                )
            )
            LaunchScreen(playersViewModel)
        }
    }
c
@rachael
It seems like the preference in a pure compose app is to not use fragments at all. Does that mean a single activity app where I have a ViewModel for every screen that's tied to that single Activity's lifecycle?
I believe Ian Lake or Adam Powell have basically said that if you're building a pure compose app, then you can likely declare you're handling all config changes in the AndroidManifest, and then you wouldn't even need an AAC ViewModel since the main benefit of AAC VM is that it simplifies config changes for you.
i
The Hilt integration would be the other nice part of Jetpack ViewModels
f
@Gabriel i was talking about using @Assisted The injected factories must be in the activity for now
g
👍