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

Dmi*_*tri 5 android kotlin android-studio android-jetpack-compose

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

...直到我介绍这个库:

实现“androidx.navigation:navigation-compose:2.5.0-rc02”

现在编译突然失败:

仅允许使用 -Xjvm-default 选项从具有“@JvmDefault”成员的接口继承

(错误指向:ViewModelProvider.Factory

为什么?导航带来了什么?(我确实确认 100% 是导航库导致的,将其删除,错误就消失了)

注意:Q 不是关于如何解决它,编译器明确建议它,添加这些参数 - freeCompilerArgs += "-Xjvm-default=all"。问是关于为什么会发生这种情况。

Dmi*_*tri 9

好的,找到了。问题是,引入 compose 导航后,版本 2.5.0-rc 还将 androidx.lifecycle 更新为 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);
    }
Run Code Online (Sandbox Code Playgroud)

请注意一种方法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)

       
          ...
        }
Run Code Online (Sandbox Code Playgroud)

这就解释了,这个接口现在是默认实现接口,要继承它,需要添加编译器参数,按照编译器的建议(freeCompilerArgs +=“-Xjvm-default=all”)。