Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't getByClass ViewModel from ViewModelFactory with empty parameters #236

Closed
stanbar opened this issue Sep 17, 2018 · 18 comments
Closed
Labels
android status:checking currently in analysis - discussion or need more detailed specs

Comments

@stanbar
Copy link

stanbar commented Sep 17, 2018

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

val global = module {
    single { PreferenceManager.getDefaultSharedPreferences(get()) as SharedPreferences }
}
val coilModule = module {
    viewModel { CoilViewModel(get()) }
}
@luna-vulpo
Copy link

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().

@stanbar
Copy link
Author

stanbar commented Sep 18, 2018

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 }

@luna-vulpo
Copy link

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.

@arnaudgiuliani
Copy link
Member

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?

@stanbar
Copy link
Author

stanbar commented Sep 19, 2018

Right, so it can randomly become null if GC decides so?

@arnaudgiuliani
Copy link
Member

Why this line binding.viewModel = viewModel // <-- It throws here in your code?

@arnaudgiuliani arnaudgiuliani added android status:checking currently in analysis - discussion or need more detailed specs labels Sep 19, 2018
@stanbar
Copy link
Author

stanbar commented Sep 19, 2018

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.

@arnaudgiuliani
Copy link
Member

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.

@stanbar
Copy link
Author

stanbar commented Sep 19, 2018

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

@frontiertsymbal
Copy link

The same issue. Can't getByClass ViewModel from ViewModelFactory with empty parameters on app start.

@arnaudgiuliani
Copy link
Member

Don't worry, I'm on it. 👍

@TomWayne98
Copy link

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

@arnaudgiuliani
Copy link
Member

Can you try with 1.0.1-alpha-1? (just published a fix)

@frontiertsymbal
Copy link

Testing 1.0.1-alpha-1

@TomWayne98
Copy link

Just starting testing 1.0.1-alpha-1 in our team. We will let you know, whether the problem is solved or not. Thanks

@TomWayne98
Copy link

It looks like everything works now. Thank you.

@arnaudgiuliani
Copy link
Member

nice :)

@arnaudgiuliani
Copy link
Member

Fixed in 1.0.1 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
android status:checking currently in analysis - discussion or need more detailed specs
Projects
None yet
Development

No branches or pull requests

5 participants