Describe the bug
I'm getting
Fatal Exception: java.lang.IllegalStateException
from
org.koin.androidx.viewmodel.ViewModelFactory.create (ViewModelFactory.kt:44)
that says
Can't getByClass ViewModel from ViewModelFactory with empty parameters
when i do
class CoilFragment : BaseFragment(){
private lateinit var binding: FragmentCoilBinding
private val viewModel: CoilViewModel by viewModel()
...
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
binding = FragmentCoilBinding.inflate(inflater, container, false)
binding.fragment = this
binding.viewModel = viewModel // <-- It throws here
}
}
class CoilViewModel(val sharedPreferences: SharedPreferences) : ViewModel(){
// nothing special here
}
Koin project used and used version (please complete the following information):
koin_version = "1.0.0"
implementation "org.koin:koin-android:$koin_version"
implementation "org.koin:koin-androidx-scope:$koin_version"
implementation "org.koin:koin-androidx-viewmodel:$koin_version"
Additional moduleDefinition
```kotlin
val global = module {
single { PreferenceManager.getDefaultSharedPreferences(get()) as SharedPreferences }
}
val coilModule = module {
viewModel { CoilViewModel(get()) }
}
Put logs with KOIN tag.
But I think that in single { PreferenceManager.getDefaultSharedPreferences(get()) as SharedPreferences } isn't passed context. Did you have a global access to main application class? try pass it instead get().
The problem is that I can't reproduce this crash. I can only see it via Firebase Crashlytisc.
I found that it happens also in different places in my code.
org.koin.androidx.viewmodel.ViewModelFactory.create (ViewModelFactory.kt:44)
androidx.lifecycle.ViewModelProvider.get (ViewModelProvider.java:135)
androidx.lifecycle.ViewModelProvider.get (ViewModelProvider.java:103)
org.koin.androidx.viewmodel.ext.android.LifecycleOwnerExtKt.getViewModelByClass (LifecycleOwnerExt.kt:105)
org.koin.androidx.viewmodel.ext.android.LifecycleOwnerExtKt$viewModelByClass$1.invoke (LifecycleOwnerExt.kt:63)
org.koin.androidx.viewmodel.ext.android.LifecycleOwnerExtKt$viewModelByClass$1.invoke (LifecycleOwnerExt.kt)
kotlin.SynchronizedLazyImpl.getValue (LazyJVM.kt:74)
com.stasbar.fragments.liquid.LiquidFragment.getViewModel (LiquidFragment.kt)
com.stasbar.fragments.liquid.LiquidFragment.setLiquid (LiquidFragment.kt:312)
com.stasbar.fragments.liquid.LiquidFragment.onCreate (LiquidFragment.kt:97)
org.koin.androidx.viewmodel.ViewModelFactory.create (ViewModelFactory.kt:44)
androidx.lifecycle.ViewModelProvider.get (ViewModelProvider.java:135)
androidx.lifecycle.ViewModelProvider.get (ViewModelProvider.java:103)
org.koin.androidx.viewmodel.ext.android.LifecycleOwnerExtKt.getViewModelByClass (LifecycleOwnerExt.kt:105)
org.koin.androidx.viewmodel.ext.android.LifecycleOwnerExtKt$viewModelByClass$1.invoke (LifecycleOwnerExt.kt:63)
org.koin.androidx.viewmodel.ext.android.LifecycleOwnerExtKt$viewModelByClass$1.invoke (LifecycleOwnerExt.kt)
kotlin.SynchronizedLazyImpl.getValue (LazyJVM.kt:74)
com.stasbar.fragments.PhotosFragment.getViewModel (PhotosFragment.kt)
com.stasbar.fragments.PhotosFragment.onCreateView (PhotosFragment.kt:73)
It happens only to 0.01% of my users, but still.
I'm not sure what you meant by
Did you have a global access to main application class? try pass it instead get().
something like that ?
single { PreferenceManager.getDefaultSharedPreferences(androidApplication()) as SharedPreferences }
Looking at https://github.com/InsertKoinIO/koin/blob/88a917ebd45b6ddfeeb96904573e8baa6d6c9a11/koin-projects/koin-android-viewmodel/src/main/java/org/koin/android/viewmodel/ViewModelFactory.kt
and having regard to the fact that it happens only to 0.01% of users
So it seems that some how WeakReference contains null.
Yep, in this case, it can come from unallocated parameters from ViewModel factory. But why :/
Do your app goes in background or something like that?
Right, so it can randomly become null if GC decides so?
Why this line binding.viewModel = viewModel // <-- It throws here in your code?
Do your app goes in background or something like that?
As far as I know, Android Apps can go to background anytime system decide so.
I'm curious why do you use WeakReference there ?
Why this line binding.viewModel = viewModel // <-- It throws here in your code?
So I can use viewModel instance in my XML layout. But I'm sure that it doesn't matter, because in other fragments (PhotosFragment.kt, LiquidFragment.kt) which also crashes, I'm not using DataBinding.
INteresting question. My initial thought is that we need to transmit parameters to the ViewModelFactory, to help Koin create the right instance behind that.
But seems that my design with such call is problematic: need to gc arguments if not used. And in your case, you get a gc.
I think that the AndroidX behavior seems a bit different. :/
Does your VM has been created?
Perhaps rethink this VM interaction/creation should help it.
Sorry but, I don't know how to answer your question Does your VM has been created?
Neither Firebase Crashlitics provide such information, nor I can reproduce the crash
The same issue. Can't getByClass ViewModel from ViewModelFactory with empty parameters on app start.
Don't worry, I'm on it. 馃憤
Same issue here:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.ilab.spaceti.mvvm/com.ilab.spaceti.ui.splashscreen.SplashActivity}: java.lang.IllegalStateException: Can't getByClass ViewModel from ViewModelFactory with empty parameters
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2861)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2943)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1630)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6626)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:811)
Caused by: java.lang.IllegalStateException: Can't getByClass ViewModel from ViewModelFactory with empty parameters
at org.koin.android.viewmodel.ViewModelFactory.create(ViewModelFactory.kt:44)
at android.arch.lifecycle.ViewModelProvider.get(ViewModelProvider.java:134)
at android.arch.lifecycle.ViewModelProvider.get(ViewModelProvider.java:102)
at org.koin.android.viewmodel.ext.android.LifecycleOwnerExtKt.getViewModelByClass(LifecycleOwnerExt.kt:105)
at com.ilab.spaceti.ui.splashscreen.SplashActivity.initViewModel(SplashActivity.kt:114)
at com.ilab.spaceti.ui.base.BaseActivity.onCreate(BaseActivity.kt:77)
at com.ilab.spaceti.ui.splashscreen.SplashActivity.onCreate(SplashActivity.kt:46)
at android.app.Activity.performCreate(Activity.java:7008)
at android.app.Activity.performCreate(Activity.java:6999)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1236)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2814)
It happens in 1 of 10 cases.
Good luck with fixing. And thanks for your work man, its excelent
Can you try with 1.0.1-alpha-1? (just published a fix)
Testing 1.0.1-alpha-1
Just starting testing 1.0.1-alpha-1 in our team. We will let you know, whether the problem is solved or not. Thanks
It looks like everything works now. Thank you.
nice :)
Fixed in 1.0.1 馃憤
Most helpful comment
Don't worry, I'm on it. 馃憤