将ViewModel定义移动到包级别方法中

我想动议:

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) } 

但是这给了我两个错误:

在这里输入图像描述

在这里输入图像描述


问题:有没有办法来完成这个?

您的T1参数必须是FragmentFragmentActivity类型。 目前没有。
另外,要调用::class.java ,类型必须是不可空的。 目前是T2: Any? 。 而且, T2必须扩展ViewModel
最后,对于一个简单的API,你可以使用一个具体的类型 。

你可能想写:

 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

这应该做的伎俩:

 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可能是你的函数中的任何类型,但是方法只需要一个Fragment或一个FragmentActivity 。 使用T1: FragmentT1限定为Fragment (当然,您也可以创建这个FragmentActivity )。

第二个问题似乎是targetViewModelClass可能是null,你可以通过将T2限制为Any的子类型来处理这个问题,它是Kotlin中所有非空类型的基类。 这将保证null不能作为参数传入。

最后,根据@Kirill Rakhman的建议,我调整了第二个参数,以便可以用KClass实例调用该函数。

这里是关于通用约束和通用 类型参数的官方文档。