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
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.
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.
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.
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() { .... }
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With