-
-
Save Zhuinden/a8f3d0e98253baab8ebd7147eb6beaa7 to your computer and use it in GitHub Desktop.
@Singleton | |
@Component | |
class ApplicationComponent { | |
fun myViewModelProvider(): Provider<MyViewModel> | |
} |
class MyFragment: Fragment() { | |
lateinit var viewModel: MyViewModel | |
override fun onCreate(savedInstanceState: Bundle?) { | |
super.onCreate(savedInstanceState) | |
val component = (requireActivity().application as MyApplication).component | |
viewModel = createViewModel { component.myViewModelProvider().get() } | |
} | |
} |
class MyViewModel @Inject constructor(): ViewModel() { | |
} |
inline fun <reified T: ViewModel> ViewModelStoreOwner.createViewModel(crossinline factory: () -> T): T = T::class.java.let { clazz -> | |
ViewModelProvider(this, object: ViewModelProvider.Factory { | |
override fun <T : ViewModel?> create(modelClass: Class<T>): T { | |
if(modelClass == clazz) { | |
@Suppress("UNCHECKED_CAST") | |
return factory() as T | |
} | |
throw IllegalArgumentException("Unexpected argument: $modelClass") | |
} | |
}).get(clazz) | |
} | |
Thanks for the note, I was thinking if there are any downsides but I can't see one. This is a great addition and therefore updated the gist. Thanks!
this code doesn't compile :-) Where does the clazz
property come from? Also this line if(modelClass == T::class.java) {
does not compile, because in that context T is not reified. And you cannot use reified
in the overriding function. Also it uses deprecated ViewModelProviders
I believe this is the working and up-to-date version:
inline fun <reified T: ViewModel> ViewModelStoreOwner.createViewModel(crossinline factory: () -> T): T {
val clazz = T::class.java
return ViewModelProvider(this, object : ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
if (modelClass == clazz) {
@Suppress("UNCHECKED_CAST")
return factory() as T
}
throw IllegalArgumentException("Unexpected argument: $modelClass")
}
}).get(clazz)
}
That's what I get for trying to remove a .let { clazz - >
and make the example a bit clearer, but do that only in a Gist π€ I'll just copy the real thing when I'm near my pc
Thanks for letting me know, I've just replaced it with the real code instead. Now it can't not work.
I'd also suggest to update the example to not use ViewModelProviders
. It's deprecated: https://developer.android.com/reference/androidx/lifecycle/ViewModelProviders
that's what I get for copy-pasting from Stack Overflow from an answer I should clearly update as it's like a year old π
But yes, you are right. Now I've updated both.
@Zhuinden you should be able to have a single
createViewModel
if you useViewModelStoreOwner
as the receiver.put all together you landed on almost exactly the way i've been doing it for almost 2 years. π
https://gist.github.com/trevjonez/0535c396b7b79a8fa85827f79f543c52