I'm trying to create an extension function that return a viewmodel by lazy, but i get an error about viewmodelFactory in't initialized, when i use the by lazy in the same Fragment works fine,
Example (Works fine):
@Inject
lateinit var viewModelFactory: ViewModelProvider.Factory
private val listViewModel by lazy {
ViewModelProvider(this, viewModelFactory)[ListViewModel::class]
}
But when I extract it to an Extension function this fails
Example (Error):
inline fun <reified VM : ViewModel> Fragment.provideViewModel(
viewModelFactory: ViewModelProvider.Factory
): Lazy<VM> = lazy {
ViewModelProvider(this, viewModelFactory)[VM::class.java]
}
@Inject
lateinit var viewModelFactory: ViewModelProvider.Factory
private val listViewModel by provideViewModel<ListViewModel>(viewModelFactory)
Having a look at what happens behind the scenes, it seems like inline functions are the cause. When you decompile the Kotlin code into Java you see that Kotlin treats an inline function with a special wrapper class which unfortunately takes in the function arguments as constructor parameters:
this.viewModel$delegate = LazyKt.lazy((Function0)(new ActivityMain$$special$$inlined$provideViewModel$1(this, viewModelFactory$iv)));
so it requires viewModelFactory$iv
which represents the lateinit
factory to be initialised:
Factory var10001 = this.fac;
if (var10001 == null) {
Intrinsics.throwUninitializedPropertyAccessException("fac");
}
androidx.lifecycle.ViewModelProvider.Factory viewModelFactory$iv = (androidx.lifecycle.ViewModelProvider.Factory)var10001;
So this is clearly an issue with Kotlin and Dagger's interoperability and I doubt has any solution other than to change the way you're implementing things.