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

getViewModel crash intermittently with NullPointerException / IllegalArgumentException #4191

Open
vid-stefang opened this issue Dec 15, 2023 · 7 comments

Comments

@vid-stefang
Copy link

I'm migrating Dagger 2 to Hilt (2.48.1) and applying @AndroidEntryPoint and @HiltViewModel in my SplashScreen.
In latest release, we got some crash reports in my screen:
firebase-crash
All of them actually mention the same thing:
Screenshot from 2023-12-15 11-08-42

My SplashScreen is quite simple:

@HiltViewModel
class SplashScreenViewModel @Inject constructor(
    private val dispatcher: CustomDispatchers
) : ViewModel() {
...
}

@AndroidEntryPoint
@SuppressLint("CustomSplashScreen")
class SplashScreen : AppCompatActivity() {

    private val viewModel: SplashScreenViewModel by viewModels() // this is SplashScreen.kt line 18

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        lifecycleScope.launch { // this is SplashScreen.kt line 26
            viewModel.launchEvent.collect { ... }
        }
    }
}

// Hilt_SplashScreen.java
  @Override
  public ViewModelProvider.Factory getDefaultViewModelProviderFactory() {
    // line below is Hilt_SplashScreen.java:75
    return DefaultViewModelFactories.getActivityFactory(this, super.getDefaultViewModelProviderFactory());
  }

How can we resolve this intermittent crash in that SplashScreen?

I'm using kapt, AGP: 8.1.2, Kotlin: 1.9.10, Dagger & Hilt: 2.48.1, Java 17
And all of those crashes happen in Android 7 and 6 only (so far)

@Chang-Eric
Copy link
Member

Are you able to provide more of the stacktrace? It is hard to tell what is going on.

So far based on what I can see though, I have trouble imagining that this is something in Hilt. I don't think we call dataSize() in any of our generated code, but would need the whole stacktrace to know more. Also, IllegalArgumentException by itself with no stack is very hard to know what is going on there.

@vid-stefang
Copy link
Author

vid-stefang commented Dec 27, 2023

Sure @Chang-Eric , these are the stack traces:

// Case 1
Fatal Exception: java.lang.IllegalArgumentException:
       at android.os.Parcel.nativeAppendFrom(Parcel.java)
       at android.os.Parcel.appendFrom(Parcel.java:453)
       at android.os.BaseBundle.<init>(BaseBundle.java:126)
       at android.os.Bundle.<init>(Bundle.java:102)
       at android.content.Intent.getExtras(Intent.java:5724)
       at androidx.activity.ComponentActivity.getDefaultViewModelProviderFactory(ComponentActivity.java:654)
       at com.myapp.android.splash.Hilt_SplashScreen.getDefaultViewModelProviderFactory(Hilt_SplashScreen.java:75)
       at androidx.activity.ActivityViewModelLazyKt$viewModels$factoryPromise$2.invoke(ActivityViewModelLazy.kt:80)
       at com.myapp.android.splash.SplashScreen$special$$inlined$viewModels$default$1.invoke(ActivityViewModelLazy.kt:80)
       at com.myapp.android.splash.SplashScreen$special$$inlined$viewModels$default$1.invoke(ActivityViewModelLazy.kt:79)
       at androidx.lifecycle.ViewModelLazy.getValue(ViewModelLazy.kt:47)
       at androidx.lifecycle.ViewModelLazy.getValue(ViewModelLazy.kt:35)
       at com.myapp.android.splash.SplashScreen.getViewModel(SplashScreen.kt:18)
       at com.myapp.android.splash.SplashScreen.access$getViewModel(SplashScreen.kt:14)
       at com.myapp.android.splash.SplashScreen$onCreate$2.invokeSuspend(SplashScreen.kt:27)
       at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
       at kotlinx.coroutines.internal.DispatchedContinuationKt.resumeCancellableWith(DispatchedContinuation.kt:367)
       at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:30)
       at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable$default(Cancellable.kt:25)
       at kotlinx.coroutines.CoroutineStart.invoke(CoroutineStart.java:110)
       at kotlinx.coroutines.AbstractCoroutine.start(AbstractCoroutine.kt:126)
       at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch(BuildersKt__Builders_common.kt:56)
       at kotlinx.coroutines.BuildersKt.launch(Builders.kt:1)
       at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch$default(BuildersKt__Builders_common.kt:47)
       at kotlinx.coroutines.BuildersKt.launch$default(Builders.kt:1)
       at com.myapp.android.splash.SplashScreen.onCreate(SplashScreen.kt:26)
       at android.app.Activity.performCreate(Activity.java:6351)
       at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1114)
       at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2470)
       at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2577)
       at android.app.ActivityThread.access$1000(ActivityThread.java:166)
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1414)
       at android.os.Handler.dispatchMessage(Handler.java:102)
       at android.os.Looper.loop(Looper.java:148)
       at android.app.ActivityThread.main(ActivityThread.java:5619)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:853)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:737)

// Case 2
Fatal Exception: java.lang.NullPointerException: Attempt to invoke virtual method 'int android.os.Parcel.dataSize()' on a null object reference
       at android.os.BaseBundle.<init>(BaseBundle.java:164)
       at android.os.Bundle.<init>(Bundle.java:106)
       at android.content.Intent.getExtras(Intent.java:7186)
       at androidx.activity.ComponentActivity.getDefaultViewModelProviderFactory(ComponentActivity.java:654)
       at com.myapp.android.splash.Hilt_SplashScreen.getDefaultViewModelProviderFactory(Hilt_SplashScreen.java:75)
       at androidx.activity.ActivityViewModelLazyKt$viewModels$factoryPromise$2.invoke(ActivityViewModelLazy.kt:80)
       at com.myapp.android.splash.SplashScreen$special$$inlined$viewModels$default$1.invoke(ActivityViewModelLazy.kt:80)
       at com.myapp.android.splash.SplashScreen$special$$inlined$viewModels$default$1.invoke(ActivityViewModelLazy.kt:79)
       at androidx.lifecycle.ViewModelLazy.getValue(ViewModelLazy.kt:47)
       at androidx.lifecycle.ViewModelLazy.getValue(ViewModelLazy.kt:35)
       at com.myapp.android.splash.SplashScreen.getViewModel(SplashScreen.kt:18)
       at com.myapp.android.splash.SplashScreen.access$getViewModel(SplashScreen.kt:14)
       at com.myapp.android.splash.SplashScreen$onCreate$2.invokeSuspend(SplashScreen.kt:27)
       at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
       at kotlinx.coroutines.internal.DispatchedContinuationKt.resumeCancellableWith(DispatchedContinuation.kt:367)
       at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:30)
       at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable$default(Cancellable.kt:25)
       at kotlinx.coroutines.CoroutineStart.invoke(CoroutineStart.java:110)
       at kotlinx.coroutines.AbstractCoroutine.start(AbstractCoroutine.kt:126)
       at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch(BuildersKt__Builders_common.kt:56)
       at kotlinx.coroutines.BuildersKt.launch(Builders.kt:1)
       at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch$default(BuildersKt__Builders_common.kt:47)
       at kotlinx.coroutines.BuildersKt.launch$default(Builders.kt:1)
       at com.myapp.android.splash.SplashScreen.onCreate(SplashScreen.kt:26)
       at android.app.Activity.performCreate(Activity.java:6977)
       at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1126)
       at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2946)
       at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3064)
       at android.app.ActivityThread.-wrap14(ActivityThread.java)
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1659)
       at android.os.Handler.dispatchMessage(Handler.java:102)
       at android.os.Looper.loop(Looper.java:154)
       at android.app.ActivityThread.main(ActivityThread.java:6816)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1565)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1453)

additional info: Firebase tags it as "Early crashes", means it happens in the first 5 seconds when user open the app (I guess bcs it's splash screen).
Screenshot 2023-12-27 at 13 58 52 (1)

@Chang-Eric
Copy link
Member

Thanks for the stacktraces. I don't think this is related to Hilt. These crashes are coming from when we call through to the Activity's getDefaultViewModelProviderFactory method which means it would happen without Hilt as well. It looks like something in the Intent extras is malformed? I'm not really sure beyond that though.

@Radwa13
Copy link

Radwa13 commented Mar 4, 2024

Hello have you found any solution I get these exact crashes too.

@nico-gonzalez
Copy link

nico-gonzalez commented Mar 11, 2024

@Chang-Eric hello! we are experiencing this issue as well since some time ago in several of our activities and we were wondering if it has to do with a lifecycle issue between in the code that dagger generates for the activities annotated with @AndroidEntryPoint. In our case, the stack trace always include a reference to generated dagger.hilt.android.internal code - see stacktrace below. Let me know if you need further information

Caused by java.lang.NullPointerException
Attempt to invoke virtual method 'int android.os.Parcel.dataSize()' on a null object reference
android.os.BaseBundle.<init> (BaseBundle.java:126)
android.os.Bundle.<init> (Bundle.java:102)
android.content.Intent.getExtras (Intent.java:6569)
androidx.activity.ComponentActivity.getDefaultViewModelCreationExtras (ComponentActivity.java:655)
androidx.lifecycle.ViewModelProviderGetKt.defaultCreationExtras (ViewModelProvider.kt:359)
androidx.lifecycle.ViewModelProvider.<init> (ViewModelProvider.kt:129)
dagger.hilt.android.internal.managers.ActivityRetainedComponentManager.getViewModelProvider (ActivityRetainedComponentManager.java:100)
dagger.hilt.android.internal.managers.ActivityRetainedComponentManager.getSavedStateHandleHolder (ActivityRetainedComponentManager.java:134)
dagger.hilt.android.internal.managers.ActivityComponentManager.getSavedStateHandleHolder (ActivityComponentManager.java:76)
com.app.android.presentation.Hilt_DetailActivity.initSavedStateHandleHolder (Hilt_DetailActivity.java:53)
com.app.android.presentation.Hilt_DetailActivity.onCreate (Hilt_DetailActivity.java:64)
com.app.android.presentation.DetailActivity.onCreate (DetailActivity.kt:68)
android.app.Activity.performCreate (Activity.java:6904)
android.app.Instrumentation.callActivityOnCreate (Instrumentation.java:1136)
android.app.ActivityThread.performLaunchActivity (ActivityThread.java:3266)
android.app.ActivityThread.handleLaunchActivity (ActivityThread.java:3415)
android.app.ActivityThread.access$1100 (ActivityThread.java:229)
android.app.ActivityThread$H.handleMessage (ActivityThread.java:1821)
android.os.Handler.dispatchMessage (Handler.java:102)
android.os.Looper.loop (Looper.java:148)
android.app.ActivityThread.main (ActivityThread.java:7406)
java.lang.reflect.Method.invoke (Method.java)
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:1230)
com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1120)

@wanyingd1996
Copy link

Hi, nico, do you get this error if you directly invoke getDefaultViewModelCreationExtras from DetailActivity#onCreate? If so, it should be a malformed intent problem, and cannot be fixed from Dagger side, thanks!

@Chang-Eric
Copy link
Member

@nico-gonzalez To my knowledge, a lifecycle issue wouldn't appear as intermittent because all of this is happening on the main thread (in your stacktrace this is happening in onCreate() which is on the main thread and if we were at the wrong time in the lifecycle, that lifecycle change we're missing would also be done on the main thread), so there wouldn't really be a race unless it were unsafe to access any ViewModels in onCreate(), even after super.onCreate(), which we know shouldn't be the case. So that's why this doesn't seem like a lifecycle issue in the generated code to me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants