I have been spending a lot of time trying to figure out why in the code below (towards the end), I get an error on ViewModelProvider(this). I also tried getActivity() instead of
The cleanest implementation must use Kotlin for its advanced functions. You can either create this kotlin code in a separate Kclass or leave this answer for future users that want to know how to do this in Kotlin. Basically we are initialising the ViewModel by lazy like this:
Make sure you have this dependency:
implementation "androidx.fragment:fragment-ktx:1.2.0"
Create this helper function that accesses an internal fragment-ktx method that allows yo to create a ViewModel instance by lazy:
@MainThread
inline fun <reified VM : ViewModel> Fragment.fragmentViewModel() =
createViewModelLazy(
VM::class,
{ this.viewModelStore },
{ ViewModelFactory(Database.getDatabase(requireContext().applicationContext)) }
)
Now create a ViewModelFactory using this official java example:
https://github.com/android/architecture-components-samples/blob/master/BasicRxJavaSample/app/src/main/java/com/example/android/observability/ui/ViewModelFactory.java
Or, here is the Kotlin variant:
class ViewModelFactory(private val database: Database?) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
requireNotNull(database) { "Database must not be null" }
return when {
modelClass.isAssignableFrom(ItemSetupFragmentModel::class.java) -> {
ItemSetupFragmentModel() as T
}
else -> {
throw IllegalArgumentException("Unknown ViewModel class")
}
}
}
}
And now go inside your fragment and simply initialise your ViewModel like this
class ItemSetupFragment : Fragment() {
private val model by viewModel<ItemSetupFragmentModel>()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
model.getKids().observe(this, users -> {
// update UI
});
}
}
Hope this helps!
Firstly you need to use the latest version of lifecycle extension. It should be:
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
implementation "androidx.lifecycle:lifecycle-viewmodel:2.2.0"
or any updated version.
Then you should use requireActivity() instead of getActivity(). This way you will ensure that the activity is attached an not getting a NullPointerException.
ItemSetupFragmentModel model = new ViewModelProvider(requireActivity()).get(ItemSetupFragmentModel.class);
Note: ViewModel Overview and Declaring Dependencies
I had to restart cache after adding the library to the Gradle file.
There is no need to use requireActivity(), this is enough.
You aren't using the latest library release in which the ViewModelProvider(@NonNull ViewModelStoreOwner owner) constructor was included. You are seeing the latest docs but not using the latest library version of ViewModel.
You need to use
implementation 'androidx.lifecycle:lifecycle-viewmodel:2.2.0' // For Java
or
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0' // For kotlin extension
You should instantiate your viewModel by :
ItemSetupFragmentModel model = ViewModelProviders.of(this).get(ItemSetupFragmentModel.class);