https://kotlinlang.org logo
#compose
Title
# compose
r

rachael

03/04/2021, 5:29 PM
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

Vipulyaara

03/04/2021, 5:43 PM
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

alorma

03/04/2021, 5:53 PM
What if not using hilt?
i

Ian Lake

03/04/2021, 5:54 PM
Any call to
viewModel()
within a
NavHost
composable
will scope it to that individual screen (it doesn't matter what factory you use)
r

rachael

03/04/2021, 5:58 PM
awesome, thanks!
g

Gabriel

03/04/2021, 6:00 PM
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

Ian Lake

03/04/2021, 6:29 PM
You'd use
val playersViewModel = viewModel<PlayersViewModel>()
in Compose land: https://developer.android.com/jetpack/compose/interop#viewmodel
g

Gabriel

03/04/2021, 6:30 PM
Thanks @Ian Lake!
i

Ian Lake

03/04/2021, 6:30 PM
But yes, that would correctly scope the
PlayersViewModel
instance to only the
LaunchScreen
destination
f

FunkyMuse

03/04/2021, 9:04 PM
What about the factories for the assisted inject, they all need to be injected into the activity then passed to the composables?
g

Gabriel

03/04/2021, 9:10 PM
@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

Colton Idle

03/05/2021, 1:50 AM
@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

Ian Lake

03/05/2021, 3:25 AM
The Hilt integration would be the other nice part of Jetpack ViewModels
f

FunkyMuse

03/05/2021, 7:35 AM
@Gabriel i was talking about using @Assisted The injected factories must be in the activity for now
g

Gabriel

03/05/2021, 7:37 AM
👍