Kotlin 看不懂 ViewModelProviders.of(activity ?: fragment)
Kotlin does not understand ViewModelProviders.of(activity ?: fragment)
在我的 Fragment
中,我使用 ViewModelProviders
初始化了一个 ViewModel
。
如果不是 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(FragmentActivity) defined in androidx.lifecycle.ViewModelPro
似乎语言不允许我调用冲突的方法签名(在 of(Activity)
和 of(Fragment)
之间。(这可能是可以理解的,也许编译器只需要引用一个方法而不能 link 都在同一行。) 是这样吗?
我现在必须使用
activity?.let {
ViewModelProviders.of(it).get(MainViewModel::class.java)
} ?: run {
ViewModelProviders.of(this).get(MainViewModel::class.java)
}
有更好的方法吗?
是的,这是 编译器歧义,因为您同时传递了 activity
和 this (fragment instance)
,这在 [=20= 中有不同的实现]ViewModelProviders
.
另一种方法 是使用 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.
}
}
}
除了 Jeel 的回答,我建议如果你经常需要使用这个模式,你应该在 Fragment
上定义一个扩展函数,以避免重复。例如:
fun Fragment.getViewModelProvider() =
activity?.let(ViewModelProviders::of) ?: ViewModelProviders.of(this)
inline fun <reified T : ViewModel> Fragment.getViewModel() =
getViewModelProvider().get(T::class.java)
从那里,在任何 Fragment
中,您可以调用:
val viewModel: MainViewModel = getViewModel()
val viewModel = getViewModel<MainViewModel>()
它将避免获取提供程序的样板文件以及具体指定 Java class。
如果您使用的是 androidx,那么应该为生命周期添加两行:
def lifecycle_version = "2.2.0-rc02"
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
kapt "androidx.lifecycle:lifecycle-compiler:$lifecycle_version"
并像这样使用它:
val mainViewModel = ViewModelProvider(this).get(MainViewModel::class.java)
在我的 Fragment
中,我使用 ViewModelProviders
初始化了一个 ViewModel
。
如果不是 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(FragmentActivity) defined in androidx.lifecycle.ViewModelPro
似乎语言不允许我调用冲突的方法签名(在 of(Activity)
和 of(Fragment)
之间。(这可能是可以理解的,也许编译器只需要引用一个方法而不能 link 都在同一行。) 是这样吗?
我现在必须使用
activity?.let {
ViewModelProviders.of(it).get(MainViewModel::class.java)
} ?: run {
ViewModelProviders.of(this).get(MainViewModel::class.java)
}
有更好的方法吗?
是的,这是 编译器歧义,因为您同时传递了 activity
和 this (fragment instance)
,这在 [=20= 中有不同的实现]ViewModelProviders
.
另一种方法 是使用 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.
}
}
}
除了 Jeel 的回答,我建议如果你经常需要使用这个模式,你应该在 Fragment
上定义一个扩展函数,以避免重复。例如:
fun Fragment.getViewModelProvider() =
activity?.let(ViewModelProviders::of) ?: ViewModelProviders.of(this)
inline fun <reified T : ViewModel> Fragment.getViewModel() =
getViewModelProvider().get(T::class.java)
从那里,在任何 Fragment
中,您可以调用:
val viewModel: MainViewModel = getViewModel()
val viewModel = getViewModel<MainViewModel>()
它将避免获取提供程序的样板文件以及具体指定 Java class。
如果您使用的是 androidx,那么应该为生命周期添加两行:
def lifecycle_version = "2.2.0-rc02"
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
kapt "androidx.lifecycle:lifecycle-compiler:$lifecycle_version"
并像这样使用它:
val mainViewModel = ViewModelProvider(this).get(MainViewModel::class.java)