[英]Kotlin does not understand ViewModelProviders.of(activity ?: fragment)
Inside my Fragment
I initialize a ViewModel
using ViewModelProviders
.在我的
Fragment
我初始化ViewModel
使用ViewModelProviders
。 I want it to take its Activity
if not null
, otherwise itself ( Fragment
).如果不是
null
,我希望它采用它的Activity
,否则它本身( Fragment
)。
private val viewModel: MainViewModel by lazy {
ViewModelProviders.of(activity ?: this).get(MainViewModel::class.java)
}
None of the following functions can be called with the arguments supplied.
不能使用提供的参数调用以下函数。
- of(Fragment) defined in androidx.lifecycle.ViewModelProviders
of(Fragment) 在 androidx.lifecycle.ViewModelProviders 中定义
- of(FragmentActivity) defined in androidx.lifecycle.ViewModelPro
of(FragmentActivity) 在 androidx.lifecycle.ViewModelPro 中定义
It seems the language does not allow me to invoke conflicting method signatures (between of(Activity)
and of(Fragment)
. (It might be understandable, maybe the compiler has to reference only one method and cannot link to both on the same line.) Is that so?似乎该语言不允许我调用冲突的方法签名(在
of(Activity)
和of(Fragment)
。(这可能可以理解,也许编译器只需要引用一个方法,而不能在同一行上链接到这两个方法。 )是这样吗?
I now have to use我现在必须使用
activity?.let {
ViewModelProviders.of(it).get(MainViewModel::class.java)
} ?: run {
ViewModelProviders.of(this).get(MainViewModel::class.java)
}
Is there any better way of doing this?有没有更好的方法来做到这一点?
Yes, it's compiler ambiguity , because you're passing activity
& this (fragment instance)
at the same time which has different implementations in ViewModelProviders
.是的,这是编译器歧义,因为您同时传递
activity
和this (fragment instance)
,它在ViewModelProviders
有不同的实现。
Another approach to do this is by using when
condition like below, (although your approach is also good) :另一种方法是使用如下所示的
when
条件(尽管您的方法也不错) :
private val viewModel: MainViewModel by lazy {
return@lazy when {
activity != null -> {
ViewModelProviders.of(activity as FragmentActivity).get(MainViewModel::class.java) // you can either pass activity object
}
else -> {
ViewModelProviders.of(this).get(MainViewModel::class.java) // or pass fragment object, both are not possible at same time.
}
}
}
if you are using androidx so should add two lines for lifecycle :如果您使用的是 androidx,那么应该为生命周期添加两行:
def lifecycle_version = "2.2.0-rc02"
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
kapt "androidx.lifecycle:lifecycle-compiler:$lifecycle_version"
and use it like this :并像这样使用它:
val mainViewModel = ViewModelProvider(this).get(MainViewModel::class.java)
In addition to Jeel's answer, I'd recommend that if you commonly need to use this pattern, you should define an extension function on Fragment
for it to avoid repetition.除了 Jeel 的回答之外,我建议如果您通常需要使用这种模式,您应该在
Fragment
为其定义一个扩展函数以避免重复。 For example:例如:
fun Fragment.getViewModelProvider() =
activity?.let(ViewModelProviders::of) ?: ViewModelProviders.of(this)
inline fun <reified T : ViewModel> Fragment.getViewModel() =
getViewModelProvider().get(T::class.java)
From there, within any Fragment
you can just call either:从那里,您可以在任何
Fragment
调用:
val viewModel: MainViewModel = getViewModel()
val viewModel = getViewModel<MainViewModel>()
It'll avoid both the boilerplate of fetching the provider as well as specifying the Java class specifically.它将避免获取提供者的样板以及专门指定 Java 类。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.