Somebody wrote two extension function (Code A2) for both Fragment
and FragmentActivity
to instantiate a ViewModel
, it works well, you can see Code A1 and Code A3.
I hope to write two extension function (Code B2) for both Fragment
and FragmentActivity
to instantiate a AndroidViewModel
, you can see Code B1 and Code B3, how can I do? Thanks!
Code A1
class HomeViewModel_A(private val mDBVoiceRepository: DBVoiceRepository) : ViewModel() {
}
Code A2
inline fun <reified T : ViewModel> Fragment.getViewModel(noinline creator: (() -> T)? = null): T {
return if (creator == null)
ViewModelProvider(this).get(T::class.java)
else
ViewModelProvider(this, BaseViewModelFactory(creator)).get(T::class.java)
}
inline fun <reified T : ViewModel> FragmentActivity.getViewModel(noinline creator: (() -> T)? = null): T {
return if (creator == null)
ViewModelProvider(this).get(T::class.java)
else
ViewModelProvider(this, BaseViewModelFactory(creator)).get(T::class.java)
}
Code A3
class FragmentHome : Fragment() {
private val mHomeViewModel_A by lazy {
getViewModel {
HomeViewModel_A(provideRepository(mContext))
}
}
}
Code B1
class HomeViewModel_B(application: Application,private val mDBVoiceRepository: DBVoiceRepository) : AndroidViewModel(application) {
}
Code B2
?
Code B3
class FragmentHome : Fragment() {
private val mHomeViewModel_B by lazy {
?
}
}
The Ktx Fragments library already has a function for concisely creating a lazy delegate to retrieve a view model: Fragment.viewModels()
and FragmentActivity.viewModels()
.
These work for both ViewModel and AndroidViewModels with the default constructors (empty, or an Application parameter respectively), or you can use the trailing lambda to return a view model factory. You would use it like this:
class FragmentHome : Fragment() {
private val mHomeViewModel_B: MyViewModel by viewModels()
}
or
class FragmentHome : Fragment() {
private val mHomeViewModel_B: MyViewModel by viewModels { getMyViewModelFactory() }
}
To get something equivalent to what you have in A2, you can wrap this function to have it build a factory for you:
@Suppress("UNCHECKED_CAST")
inline fun <reified VM : ViewModel> Fragment.viewModelFactory(crossinline creator: () -> VM): Lazy<VM> {
return viewModels {
object : ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
return creator() as T
}
}
}
}
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