我有这个简单的视图模型提供程序工厂代码(从Google的一个代码示例中借用),它很高兴地执行并完美地编译…
fun <VM : ViewModel> viewModelProviderFactoryOf(
create: () -> VM
): ViewModelProvider.Factory = SimpleFactory(create)
private class SimpleFactory<VM : ViewModel>(
private val create: () -> VM
) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
val vm = create()
if (modelClass.isInstance(vm)) {
@Suppress("UNCHECKED_CAST")
return vm as T
}
throw IllegalArgumentException("Can not create ViewModel for class: $modelClass")
}
}
…直到我介绍了这个库:
实现"androidx.navigation: navigation-compose: 2.5.0-rc02"
现在突然编译失败了:
从带有'@JvmDefault'成员的接口继承只允许使用-Xjvm-default选项
(错误指向: ViewModelProvider。工厂
)为什么?导航带来了什么?(我确实100%确认是导航库导致的,删除它,错误就消失了)
注意:Q不是关于如何解决它,编译器明确建议,添加这些参数- freeCompilerArgs += "- xjvm -default=all"Q是关于为什么会发生这种情况。
找到了。问题是引入组合导航,2.5.0-rc版本也更新了androidx。生命周期到2.5.0-rc(在我的例子中是从2.3.0),在那里,他们改变了工厂接口通过添加一个具有实现的方法(也将实现添加到接口中的现有方法中)。
比较:
2.5.0之前的工厂实现:
public interface Factory {
/**
* Creates a new instance of the given {@code Class}.
* <p>
*
* @param modelClass a {@code Class} whose instance is requested
* @param <T> The type parameter for the ViewModel.
* @return a newly created ViewModel
*/
@NonNull
<T extends ViewModel> T create(@NonNull Class<T> modelClass);
}
注意一个方法,创建,而不实现
这是他们在2.5.0中重写的
public interface Factory {
/**
* Creates a new instance of the given `Class`.
*
* Default implementation throws [UnsupportedOperationException].
*
* @param modelClass a `Class` whose instance is requested
* @return a newly created ViewModel
*/
public fun <T : ViewModel> create(modelClass: Class<T>): T {
throw UnsupportedOperationException(
"Factory.create(String) is unsupported. This Factory requires " +
"`CreationExtras` to be passed into `create` method."
)
}
/**
* Creates a new instance of the given `Class`.
*
* @param modelClass a `Class` whose instance is requested
* @param extras an additional information for this creation request
* @return a newly created ViewModel
*/
public fun <T : ViewModel> create(modelClass: Class<T>, extras: CreationExtras): T =
create(modelClass)
...
}
所以这就解释了,这个接口现在是一个默认实现接口,要从它继承,需要添加编译器参数,正如编译器建议的那样(freeCompilerArgs += "-Xjvm-default=all")。
我们在添加组合库时也遇到过这种情况。我们通过在gradle文件中添加xjvm-default
选项来解决这个问题。
android {
kotlinOptions {
freeCompilerArgs += "-Xjvm-default=all"
}
}
首先,将所有的片段和活动依赖关系升级到1.5.0
,并将生命周期依赖关系升级到2.5.0
。通过这样做,您的活动和片段可以处理creationExtras
部分,而不需要您做任何事情。然后在你的工厂方法中,替换这一行:
//replace this line
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
//with this one
override fun <T : ViewModel> create(modelClass: Class<T>, extras: CreationExtras): T {
,你就可以走了。source:当使用Activity 1.5.0和Fragment 1.5.0时,这些额外的内容分别由Activity或Fragment自动提供。
这段代码为我工作
val viewModel: ViewModel by viewModels(
ownerProducer = { requireParentFragment() },
factoryProducer = { VMFactory }
)