Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android ViewModel has no zero argument constructor

I am following this documentation to learn about LiveData and ViewModel. In the doc, the ViewModel class has constructor as such,

public class UserModel extends ViewModel {   private MutableLiveData<User> user;    @Inject UserModel(MutableLiveData<User> user) {     this.user = user;   }    public void init() {     if (this.user != null) {       return;     }     this.user = new MutableLiveData<>();   }    public MutableLiveData<User> getUser() {     return user;   } } 

However, when I run the code, I get exception:

final UserViewModelviewModel = ViewModelProviders.of(this).get(UserViewModel.class); 

Caused by: java.lang.RuntimeException: Cannot create an instance of class UserViewModel Caused by: java.lang.InstantiationException: java.lang.Class has no zero argument constructor

like image 789
Prabin Timsina Avatar asked May 26 '17 05:05

Prabin Timsina


People also ask

What is Sharedviewmodel?

In android, we can use ViewModel to share data between various fragments or activities by sharing the same ViewModel among all the fragments and they can access everything defined in the ViewModel. This is one way to have communication between fragments or activities.

What is ViewModelProvider factory?

androidx.lifecycle.ViewModelProvider.Factory that can create ViewModels accessing and contributing to a saved state via SavedStateHandle received in a constructor. ViewModelProvider.NewInstanceFactory. Simple factory, which calls empty constructor on the give class. Known indirect subclasses.

How do I create an instance of ViewModel in Kotlin?

Using ViewModelProvider is the right way to create ViewModel . When the activity or fragment is created, ViewModelProvider is smart enough to figure out to reuse the first created ViewModel instance. If ViewModel doesn't change (which is likely true), using val Kotlin variable is a better option here.


2 Answers

In my case as I'm using HILT, it was lacking one annotation above the Fragment that has a ViewModel: @AndroidEntryPoint

@AndroidEntryPoint class BestFragment : Fragment() {  .... 

Of course in your ViewModel class you also need to Annotate with what HILT needs: @ViewModelInject

class BestFragmentViewModel @ViewModelInject constructor(var userManager: UserManager) : ViewModel() { .... } 
like image 109
Dimitri de Jesus Avatar answered Sep 24 '22 03:09

Dimitri de Jesus


While initializing subclasses of ViewModel using ViewModelProviders, by default it expects your UserModel class to have a zero argument constructor. In your case your constructor has the argument MutableLiveData<User> user.

One way to fix this is to have a default no arg constructor for your UserModel.

Otherwise, if you want to have a non-zero argument constructor for your ViewModel class, you may have to create a custom ViewModelFactory class to initialise your ViewModel instance, which implements the ViewModelProvider.Factory interface.

I have not tried this yet, but here's a link to an excellent Google sample for this: github.com/googlesamples/android-architecture-components. Specifically, check out this class GithubViewModelFactory.java for Java code and this class GithubViewModelFactory.kt for the corresponding Kotlin code.

like image 20
Shahbaz Ahmed Avatar answered Sep 25 '22 03:09

Shahbaz Ahmed