I had this simple viewmodel provider factory code (borrowed from one of Google's code samples), which happily obliged and compiled perfectly...
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")
}
}
... Until i introduced this library:
implementation "androidx.navigation:navigation-compose:2.5.0-rc02"
Now all of a sudden compilation fails with:
Inheritance from an interface with '@JvmDefault' members is only allowed with -Xjvm-default option
(error pointing to : ViewModelProvider.Factory )
Why? What did navigation bring in with it? (I did confirm 100% it's the navigation lib causing it, remove it, and the error is gone)
Note: Q is not about how to solve it, compiler suggests it clearly, adding these args - freeCompilerArgs = "-Xjvm-default=all". The Q is about why this is happening.
CodePudding user response:
We encountered this also when we added compose libraries. We solved it by adding the xjvm-default option to our gradle file.
android {
kotlinOptions {
freeCompilerArgs = "-Xjvm-default=all"
}
}
CodePudding user response:
OK, found it. The problem is that bringing in compose navigation, version 2.5.0-rc also updates androidx.lifecycle to 2.5.0-rc (from, in my case, 2.3.0), and in there, they changed the Factory interface by adding a method with implementation (and also adding implementation to the existing method in the interface).
Compare:
Factory implementation before 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);
}
Note one method, create, without implementation.
Here is the rewrite they did in 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)
...
}
So that explains it, this interface is now a default implementation interface, and to inherit from it, need to add the compiler args, as suggested by the compiler (freeCompilerArgs = "-Xjvm-default=all").