Android 将ViewModel定义移动到包级别方法中
我谨动议:Android 将ViewModel定义移动到包级别方法中,android,kotlin,Android,Kotlin,我谨动议: 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)
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)
}
funt1.getViewModel(目标:T1,目标视图模型类:T2):惰性{
返回ViewModelProviders.of(target.get)(targetViewModelClass::class.java)
}
但是,这给了我两个错误:
及
问题:有什么方法可以完成这项任务吗?这应该可以做到:
fun <T1: Fragment, T2: Any> T1.getViewModel(targetViewModelClass: KClass<T2>): Lazy<T2> {
return ViewModelProviders.of(this).get(targetViewModelClass.java)
}
第一个问题是T1
可以是函数中的任何类型,但是的方法只接受片段
或片段活动
。使用T1:Fragment
将T1
限制为片段
(当然,您也可以将此片段活动
)
第二个问题似乎是targetViewModelClass
可能为空,您可以通过将T2
限制为Any
的子类型来解决这一问题,Any
是Kotlin中所有不可为空类型的基类。这将保证null
不能作为该参数传入
最后,根据@Kirill-Rakhman的建议,我调整了第二个参数,以便可以使用KClass
实例调用该函数
以下是关于和的官方文档。这应该可以做到:
fun <T1: Fragment, T2: Any> T1.getViewModel(targetViewModelClass: KClass<T2>): Lazy<T2> {
return ViewModelProviders.of(this).get(targetViewModelClass.java)
}
第一个问题是T1
可以是函数中的任何类型,但是的方法只接受片段
或片段活动
。使用T1:Fragment
将T1
限制为片段
(当然,您也可以将此片段活动
)
第二个问题似乎是targetViewModelClass
可能为空,您可以通过将T2
限制为Any
的子类型来解决这一问题,Any
是Kotlin中所有不可为空类型的基类。这将保证null
不能作为该参数传入
最后,根据@Kirill-Rakhman的建议,我调整了第二个参数,以便可以使用KClass
实例调用该函数
这是关于和的正式文档。您的T1
参数必须是Fragment
或FragmentActivity
类型。目前没有。
另外,要调用::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) }
}
inline fun Fragment.getViewModel():Lazy{
返回lazy{ViewModelProviders.of(this.get)(T::class.java)}
}
您现在可以将其用作:
class MyFragment : Fragment {
fun foo() {
val viewModelLazy = getViewModel<MyViewModel>()
}
}
classmyfragment:Fragment{
fun foo(){
val viewModelLazy=getViewModel()
}
}
您可以对FragmentActivity
执行相同的操作T1
参数的类型必须为Fragment
或FragmentActivity
。目前没有。
另外,要调用::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) }
}
inline fun Fragment.getViewModel():Lazy{
返回lazy{ViewModelProviders.of(this.get)(T::class.java)}
}
您现在可以将其用作:
class MyFragment : Fragment {
fun foo() {
val viewModelLazy = getViewModel<MyViewModel>()
}
}
classmyfragment:Fragment{
fun foo(){
val viewModelLazy=getViewModel()
}
}
您可以对片段活动执行相同的操作T
需要扩展ViewModel
。我喜欢这个解决方案。要更改的一件事是returnviewmodelproviders.of(this).get(T::class.java)
应该放在lazy{…}
@Oleg Great!也许你可以用你的意思来编辑答案。我的意思是,如果一个方法返回Lazy
,返回语句必须是returnlazy{foo}
,T
需要扩展ViewModel
。我喜欢这个解决方案。要更改的一件事是returnviewmodelproviders.of(this).get(T::class.java)
应该放在lazy{…}
@Oleg Great!也许你可以用你的意思来编辑答案。我的意思是,如果一个方法返回Lazy
,返回语句必须是returnlazy{foo}
。我认为OP试图做的是将类
实例作为第二个参数传递。想一想,传递ViewModel
的实例有什么意义?如果你想检索ViewModel
?我的答案已经确定,我试图保持原始代码的精神@nhaarman在另一个答案中有一个更为惯用的解决方案:)我认为OP试图做的是将类
实例作为第二个参数传递。想一想,传递ViewModel
的实例有什么意义?如果你想检索ViewModel
?我的答案已经确定,我试图保持原始代码的精神@不过,尼亚曼在另一个答案中有更为惯用的解决方案:)