Android Studio 添加Android Jetpack编写导航库后,实现ViewModelProvider.Factory失败,并从具有“@JvmDefault”的接口继承

tp5buhyn  于 2022-11-25  发布在  Android
关注(0)|答案(4)|浏览(166)

我有这个简单的视图模型提供者工厂代码(借用自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.导航:导航-合成:2.5.0-rc 02”
现在,编译突然失败,并显示:

从具有“@JvmDefault”成员的接口继承只能与-Xjvm-default选项一起使用

(指向 * 时出错:视图模型提供器.工厂 *)
为什么?导航带来了什么?(我确认100%是导航库导致的,删除它,错误就消失了)
注意:Q不是关于如何解决它,编译器清楚地建议它,添加这些参数- freeCompilerArgs +=“-Xjvm-default=all”。Q是关于为什么会发生这种情况。

6bc51xsx

6bc51xsx1#

好的,找到了。问题是引入了compose navigation,版本2.5.0-rc也将androidx.lifecycle更新到了2.5.0-rc(在我的例子中,从2.3.0),在那里,他们通过添加一个带有实现的方法(也向接口中的现有方法添加了实现)来更改***Factory接口***。
比较:
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);
    }

请注意一个方法 create没有实现。
下面是他们在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”)。

dauxcl2d

dauxcl2d2#

我们在添加合成库时也遇到了这个问题。我们通过在gradle文件中添加xjvm-default选项来解决这个问题。

android {
  kotlinOptions {
    freeCompilerArgs +=  "-Xjvm-default=all"
  }
}
ioekq8ef

ioekq8ef3#

首先,将您的所有片段和活动依赖项升级到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 {

你就可以开始了。来源:当使用Activity 1.5.0和Fragment 1.5.0时,Activity或Fragment会分别自动提供这些额外功能。

zpgglvta

zpgglvta4#

这个代码对我很有效

val viewModel: ViewModel by viewModels(
        ownerProducer = { requireParentFragment() }, 
        factoryProducer = { VMFactory }
)

相关问题