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 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 create(modelClass: Class): 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()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
model.getKids().observe(this, users -> {
// update UI
});
}
}
Hope this helps!