Inject viewModel to @Composable

Viewed 2918

I have viewModel for my ProfileScreen.

@Composable
fun ProfileScreen() {
    val viewModel: ProfileViewModel = viewModel()
    ...
}

Every time when I call ProfileScreen, new viewModel is created. How can I created only one viewModel instance for my ProfileScreen. I tried to inject viewModel following https://insert-koin.io/docs/reference/koin-android/compose/ but when I try

val viewModel: ProfileViewModel = viewModel()

Android Studio throws error.

3 Answers

Your viewModel gets destroyed whenever you destroy the composable, it can survive re-compositions but as soon as your composable gets destroyed it will be destroyed.

What you can do is create the viewModel in a scope that lives longer than the ProfileScreen composable and then pass the viewModel as parameter to it.

Something like this should work.

@Composable 
fun MainScreen() {
     val vModel : ProfileViewModel = viewModel()
     ....
     ProfileScreen(vModel)
}

Or use remember() for save instance ViewModel between recompose calls

@Composable
fun ProfileScreen() {
    val viewModel = remember { ProfileViewModel() }
    ...
}

Also, rememberSaveable allows saving state(aka data class) between recreating of activity

If u want to use Koin to inject your view model to composable you should follow what is described in the docs.

getViewModel() - fetch instance

By calling that method Koin will search for that view model and will provide with an instance.

Here is an example of injecting view model in my app.

fun ManualControlScreen(
  onDrawerClick: () -> Unit,
  viewModel: ManualControlViewModel = getViewModel<ManualControlViewModel>()
) {
   // Your composable UI
}
Related