在添加 Android Jetpack Compose 导航库后,实现 ViewModelProvider.Factory 失败,从带有"@JvmDefault"的接口继承



我有这个简单的视图模型提供程序工厂代码(从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 }
)

相关内容

  • 没有找到相关文章

最新更新