我想搬家:
ViewModelProviders.of(this).get(FooViewModel::class.java)
进入包级方法。像这样:
fun <T1, T2> T1.getViewModel(target: T1, targetViewModelClass: T2): Lazy<T2> {
return ViewModelProviders.of(target).get(targetViewModelClass::class.java)
}
然而,这给了我2个错误:
和
问题:有没有办法完成此操作?
答案 0 :(得分:4)
您的T1
参数必须是Fragment
或FragmentActivity
类型。目前没有。
另外,要调用::class.java
,类型必须是不可为空的。目前是T2: Any?
。此外,T2
必须延长ViewModel
最后,对于简易API,您可以使用reified type。
你可能想写:
inline fun <reified T: ViewModel> Fragment.getViewModel(): Lazy<T> {
return lazy { ViewModelProviders.of(this).get(T::class.java) }
}
您现在可以将其用作:
class MyFragment : Fragment {
fun foo() {
val viewModelLazy = getViewModel<MyViewModel>()
}
}
您可以对FragmentActivity
执行相同操作。
答案 1 :(得分:1)
这应该可以解决问题:
fun <T1: Fragment, T2: Any> T1.getViewModel(targetViewModelClass: KClass<T2>): Lazy<T2> {
return ViewModelProviders.of(this).get(targetViewModelClass.java)
}
用法:
class FragmentA : Fragment() {
fun foo() {
getViewModel(SomeViewModel::class)
}
}
第一个问题是T1
可能是您函数中的任何类型,但of
方法只需要Fragment
或FragmentActivity
。使用T1: Fragment
将T1
限制为Fragment
(当然,您也可以将其设为FragmentActivity
。)
第二个问题似乎是targetViewModelClass
可能为null,您可以通过将T2
限制为Any
的子类型来处理这个问题,null
是所有类的基类Kotlin中不可空的类型。这样可以保证KClass
不能作为该参数传入。
最后,根据@Kirill Rakhman的建议,我调整了第二个参数,以便可以使用{{1}}实例调用该函数。
以下是有关generic constraints和reified type parameters的官方文档。