Assume a view model like this:
public class FooViewModel extends AndroidViewModel {
@Inject public FooViewModel(Application app, SavedStateHandle handle, Bar bar) {
// ...
}
}
I want to inject Bar using Dagger 2. I am developing on Android.
According to the SavedStateHandle docs:
You should use
SavedStateViewModelFactoryif you want to receive this object inViewModel's constructor.
However, the SavedStateViewModelFactory docs state that the factory is final which means I cannot inject Bar there, either.
So far, I have been injecting via a setter:
@Provides
FooViewModel provideFooViewModel(ViewModelStoreOwner owner, Bar bar) {
FooViewModel viewModel = new ViewModelProvider(owner).get(FooViewModel.class);
viewModel.setBar(bar);
return viewModel;
}
Is there a better way to do this?
I want to use constructor injection, mark the Bar instance variable as final and eliminate the setter.
To provide a
FooViewModel, you need a custom implementation ofAbstractSavedStateViewModelFactory.and
Note:
1.) you only get
SavedStateHandleinside theAbstractSavedStateViewModelFactory, so you won't be able to get it into your graph.2.) you can reduce the length of that provider by using https://github.com/square/AssistedInject. Theoretically AutoFactory would also work, but it seems unmaintained in comparison.
3.) you won't be able to get
@Injecton your ViewModel.This answer was partly adapted from https://github.com/Zhuinden/DaggerViewModelExperiment/blob/c3cbf0a5bc85467cec08755fcc152db5e8c55f91/app/src/main/java/com/zhuinden/daggerviewmodelexperiment/features/second/SecondFragment.kt#L32-L47 .