I am using Hilt for Dependency Injection specially for injecting into ViewModel. Also wanted to scope ViewModel to NavGraph. To do this, got the ViewModelStoreOwner by passing the NavGraph and now creating ViewModel by passing the store instance provided by the navgraph to ViewModelProvider. The problem I'm facing is, as I'm passing only the store instance to get the ViewModelProvider without any Factory, since Hilt will implement that, I'm getting build error has no zero argument constructor. When saw the source code I found that as I'm providing only store instance as an argument and no factory, a simple factory is being provided automatically and as the provided factory has no arguments, hence this error.
How to solve this?
The method being called from source (ViewModelProvider.java)-
* Creates {@code ViewModelProvider}. This will create {@code ViewModels}
* and retain them in a store of the given {@code ViewModelStoreOwner}.
* <p>
* This method will use the
* {@link HasDefaultViewModelProviderFactory#getDefaultViewModelProviderFactory() default factory}
* if the owner implements {@link HasDefaultViewModelProviderFactory}. Otherwise, a
* {@link NewInstanceFactory} will be used.
*/
public ViewModelProvider(@NonNull ViewModelStoreOwner owner) {
this(owner.getViewModelStore(), owner instanceof HasDefaultViewModelProviderFactory
? ((HasDefaultViewModelProviderFactory) owner).getDefaultViewModelProviderFactory()
: NewInstanceFactory.getInstance());
}
My ViewModel Class that requires dependency injection-
private Repository repository;
private MutableLiveData<FeatureCollection> featureCollection = new MutableLiveData<>();
private MutableLiveData<Boolean> loading = new MutableLiveData<>();
private Disposable disposable;
@ViewModelInject
public QuakeListViewModel(Repository repository) {
this.repository = repository;
}
My Fragment class-
private FragmentQuakeListBinding _binding;
private QuakeListViewModel _viewModel;
private ViewModelStoreOwner viewModelStoreOwner;
private NavController _navController;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
_navController = NavHostFragment.findNavController(this);
viewModelStoreOwner = _navController.getViewModelStoreOwner(R.id.main_nav_graph);
}
public View onCreateView(@NotNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
//other implementation
_viewModel = new ViewModelProvider(viewModelStoreOwner).get(QuakeListViewModel.class);
//return binding.root
}
Any help would be appreciated
Thanks
As per the Integration with the Jetpack navigation library documentation:
If your ViewModel is scoped to the navigation graph, use the
defaultViewModelProviderFactory
object that is available to activities and fragments that are annotated with@AndroidEntryPoint
.
So you can use:
_viewModel = new ViewModelProvider(viewModelStoreOwner,
getDefaultViewModelProviderFactory()).get(QuakeListViewModel.class);