7

When I want to share a view model between various views I would use by viewmodels. I recently began looking into hilt and was wondering if hiltviewmodel would accomplish the same thing? That is to allow me to share a single(same instance) of a viewmodel?

james
  • 2,595
  • 9
  • 43
  • 70

2 Answers2

4

by viewModels():

  1. property delegate.
  2. the first time create, next time return the same instance(in the same scope, the scope is the same activity)

= hiltViewModel():

  1. only used in @Composable annotated function.
  2. the first time create, next time return the same instance(in the same scope, the scope is NavGraph, if no graph, fragment/activity)

you 'd best build a demo and practise it, and log the instance to see if the same instance.

val viewModel: ViewModelA by viewModels()

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContent {
        HiltDemoTheme {
            val viewModel2: ViewModelA = hiltViewModel()
            val viewModel3: ViewModelA = viewModel()
            val viewModel4: ViewModelA by viewModels()
            Log.d("Jeck", "$viewModel")
            Log.d("Jeck", "$viewModel2")
            Log.d("Jeck", "$viewModel3")
            Log.d("Jeck", "$viewModel4")// the four get the same instance
            Surface(
                modifier = Modifier.fillMaxSize(),
                color = MaterialTheme.colors.background
            ) {
                
            }
        }
    }

Documentation: Hilt and Navigation

When using Navigation Compose, always use the hiltViewModel composable function to obtain an instance of your @HiltViewModel annotated ViewModel. This works with fragments or activities that are annotated with @AndroidEntryPoint.

leo
  • 113
  • 3
  • 11
JeckOnly
  • 347
  • 2
  • 10
0

The ViewModel annotated with @HiltViewModel will be available for creation by the HiltViewModelFactory and can be retrieved by default in an Activity or Fragment annotated with @AndroidEntryPoint by using ViewModelProvider or the by viewModels().

Also, by viewModels returns a property delegate to access ViewModel by default scoped to the fragment. Remember viewModels is not only used with Hilt, but it can be used to provide simple ViewModel instances as well when not using Hilt.

On the other hand, @HiltViewModel, tells Hilt that this ViewModel can be injected into other classes marked with @AndroidEntryPoint as well as allowing Hilt to inject other dependencies into this ViewModel.


All Hilt ViewModels are provided by the ViewModelComponent which follows the same lifecycle as a ViewModel, and as such, can survive configuration changes. To scope a dependency to a ViewModel use the @ViewModelScoped annotation.
A @ViewModelScoped type will make it so that a single instance of the scoped type is provided across all dependencies injected into the ViewModel. Other instances of a ViewModel that request the scoped instance will receive a different instance.
If a single instance needs to be shared across various ViewModels, then it should be scoped using either @ActivityRetainedScoped or @Singleton.

[Source: https://developer.android.com/training/dependency-injection/hilt-jetpack#viewmodelscoped]


And if the shared/single ViewModel is among different fragments, you could bind the lifecycle of the injected ViewModel to the parent Activity by by activityViewModels.


More information:
https://dagger.dev/api/latest/dagger/hilt/android/lifecycle/HiltViewModel.html & https://dagger.dev/hilt/view-model.html &
https://developer.android.com/training/dependency-injection/hilt-jetpack

Dr.jacky
  • 3,341
  • 6
  • 53
  • 91