LocalViewModelStoreOwner seems to free my model even when it's needed

Viewed 73

My app crashes after resuming from being in background for a long time. For me it looks like this happens because one or more models are released by LocalViewModelStoreOwner even when those models are still needed.

How can I prevent the crashes?

In my app I use an ViewModelStoreOwner instance provided by LocalViewModelStoreOwner.current to access view models of the views in previous navigation stack entries. I access them like this

val prevViewModel: PrevViewModel = viewModel(viewModelStoreOwner)
val viewModel: ThisViewModel = viewModel(
    viewModelStoreOwner = viewModelStoreOwner,
    factory = ThisViewModel.provideFactory(
        /* uses prevViewModel for callbacks, etc. */
    )
)

This works fine, but in some cases when the app resuming I get a crash like this

15863-15863/? E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.myapp, PID: 15863
java.lang.RuntimeException: Cannot create an instance of class com.myapp.ui.prev.PrevViewModel
    at androidx.lifecycle.ViewModelProvider$NewInstanceFactory.create(ViewModelProvider.kt:204)
    at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.kt:322)
    at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.kt:304)
    at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.kt:278)
    at androidx.lifecycle.SavedStateViewModelFactory.create(SavedStateViewModelFactory.kt:128)
    at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.kt:187)
    at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.kt:153)
    at androidx.lifecycle.viewmodel.compose.ViewModelKt.get(ViewModel.kt:215)
    at androidx.lifecycle.viewmodel.compose.ViewModelKt.viewModel(ViewModel.kt:156)
    at com.myapp.ui.navigation.PrevDestinationsKt.AComposable(PrevDestinations.kt:120)
    at com.myapp.ui.navigation.PrevDestinationsKt.access$AComposable(PrevDestinations.kt:1)
    at com.myapp.ui.navigation.PrevDestinationsKt$PrevDestinations$2.invoke(PrevDestinations.kt:37)
    at com.myapp.ui.navigation.PrevDestinationsKt$PrevDestinations$2.invoke(PrevDestinations.kt:36)
    at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:116)
    at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
    at androidx.navigation.compose.NavHostKt$NavHost$4$2.invoke(NavHost.kt:163)
    at androidx.navigation.compose.NavHostKt$NavHost$4$2.invoke(NavHost.kt:162)
    at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
    at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
    at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228)
    at androidx.compose.runtime.saveable.SaveableStateHolderImpl.SaveableStateProvider(SaveableStateHolder.kt:84)
    at androidx.navigation.compose.NavBackStackEntryProviderKt.SaveableStateProvider(NavBackStackEntryProvider.kt:60)
    at androidx.navigation.compose.NavBackStackEntryProviderKt.access$SaveableStateProvider(NavBackStackEntryProvider.kt:1)
    at androidx.navigation.compose.NavBackStackEntryProviderKt$LocalOwnersProvider$1.invoke(NavBackStackEntryProvider.kt:52)
    at androidx.navigation.compose.NavBackStackEntryProviderKt$LocalOwnersProvider$1.invoke(NavBackStackEntryProvider.kt:51)
    at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
    at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
    at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228)
    at androidx.navigation.compose.NavBackStackEntryProviderKt.LocalOwnersProvider(NavBackStackEntryProvider.kt:47)
    at androidx.navigation.compose.NavHostKt$NavHost$4.invoke(NavHost.kt:162)
    at androidx.navigation.compose.NavHostKt$NavHost$4.invoke(NavHost.kt:141)
    at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:116)
    at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
    at androidx.compose.animation.CrossfadeKt$Crossfade$4$1.invoke(Crossfade.kt:115)
    at androidx.compose.animation.CrossfadeKt$Crossfade$4$1.invoke(Crossfade.kt:110)
    at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
    at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
    at androidx.compose.animation.CrossfadeKt.Crossfade(Crossfade.kt:124)
    at androidx.compose.animation.CrossfadeKt.Crossfade(Crossfade.kt:55)
    at androidx.navigation.compose.NavHostKt.NavHost(NavHost.kt:141)
    at androidx.navigation.compose.NavHostKt.NavHost(NavHost.kt:67)
15863-15863/? E/AndroidRuntime:     at com.myapp.ui.navigation.MyNavGraphKt.MyNavGraph(MyNavGraph.kt:27)
    at com.myapp.ui.MainActivityContentKt$MainActivityContent$1$4.invoke(MainActivityContent.kt:93)
    at com.myapp.ui.MainActivityContentKt$MainActivityContent$1$4.invoke(MainActivityContent.kt:87)
    at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:116)
    at androidx.compose.runtime.internal.ComposableLambdaImpl$invoke$1.invoke(ComposableLambda.jvm.kt:127)
    at androidx.compose.runtime.internal.ComposableLambdaImpl$invoke$1.invoke(ComposableLambda.jvm.kt:127)
    at androidx.compose.runtime.RecomposeScopeImpl.compose(RecomposeScopeImpl.kt:145)
    at androidx.compose.runtime.ComposerImpl.recomposeToGroupEnd(Composer.kt:2351)
    at androidx.compose.runtime.ComposerImpl.skipCurrentGroup(Composer.kt:2618)
    at androidx.compose.runtime.ComposerImpl$doCompose$2$5.invoke(Composer.kt:3205)
    at androidx.compose.runtime.ComposerImpl$doCompose$2$5.invoke(Composer.kt:3183)
    at androidx.compose.runtime.SnapshotStateKt__DerivedStateKt.observeDerivedStateRecalculations(DerivedState.kt:252)
    at androidx.compose.runtime.SnapshotStateKt.observeDerivedStateRecalculations(Unknown Source:1)
    at androidx.compose.runtime.ComposerImpl.doCompose(Composer.kt:3183)
    at androidx.compose.runtime.ComposerImpl.recompose$runtime_release(Composer.kt:3148)
    at androidx.compose.runtime.CompositionImpl.recompose(Composition.kt:746)
    at androidx.compose.runtime.Recomposer.performRecompose(Recomposer.kt:876)
    at androidx.compose.runtime.Recomposer.access$performRecompose(Recomposer.kt:107)
    at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$2.invoke(Recomposer.kt:485)
    at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$2.invoke(Recomposer.kt:454)
    at androidx.compose.ui.platform.AndroidUiFrameClock$withFrameNanos$2$callback$1.doFrame(AndroidUiFrameClock.android.kt:34)
    at androidx.compose.ui.platform.AndroidUiDispatcher.performFrameDispatch(AndroidUiDispatcher.android.kt:109)
    at androidx.compose.ui.platform.AndroidUiDispatcher.access$performFrameDispatch(AndroidUiDispatcher.android.kt:41)
    at androidx.compose.ui.platform.AndroidUiDispatcher$dispatchCallback$1.doFrame(AndroidUiDispatcher.android.kt:69)
    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:909)
    at android.view.Choreographer.doCallbacks(Choreographer.java:723)
    at android.view.Choreographer.doFrame(Choreographer.java:655)
    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:897)
    at android.os.Handler.handleCallback(Handler.java:789)
    at android.os.Handler.dispatchMessage(Handler.java:98)
    at android.os.Looper.loop(Looper.java:164)
    at android.app.ActivityThread.main(ActivityThread.java:6944)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)
 Caused by: java.lang.InstantiationException: java.lang.Class<com.myapp.ui.prev.PrevViewModel> has no zero argument constructor
    at java.lang.Class.newInstance(Native Method)
    at androidx.lifecycle.ViewModelProvider$NewInstanceFactory.create(ViewModelProvider.kt:202)
        ... 75 more
0 Answers
Related