Hilt - injecting ViewModel via navGraphViewModels issue
See original GitHub issueHello,
I had an issue with restoring state of injected viewmodel via navGraphViewModels.
I saw the recommended way for injectig viewmodels with the Jetpack navigation library (https://github.com/google/dagger/issues/1935), 2, however after process death ViewModel
is not restored correctly on the second screen of navGraph.
I created demo project which demostrates the issue. We have a nested navigation graph R.id.nested
which consists of 2 fragments. Those 2 fragments shares MainViewModel
and MainViewModel2
which are completely similar and contains LiveData<String>
.
The only difference is that first ViewModel initialized with fragment’s defaultViewModelProviderFactory
as recommended with Hilt, while second is initialized without passing custom factory, so uses backStackEntry’s defaultViewModelProviderFactory
(will not work when Hilt is used, but to demosntrate the problem).
private val viewModel by navGraphViewModels<MainViewModel>(R.id.nested) {
defaultViewModelProviderFactory
}
private val viewModel2 by navGraphViewModels<MainViewModel2>(R.id.nested)
First fragment in nested graph sets message to both viewmodels and then opens Second fragment.
With Don't keep activities
enabled, putting app to background and back, triggers app process death and restore.
After process restore, MainViewModel
doesn’t have the value from First fragment and shows the default one, while MainViewModel2
is restored correctly and displays proper message.
- Enter message on FirstFragment and open SecondFragment.
On SecondFragment both viewmodels have correct values. - Background app with
Don't keep activities
to trigger process death and come back.
On SecondFragment first viewmodel doesn’t have restored value, second viewmodel has as expected. - Press back to return on FirstFragment and open SecondFragment again
On SecondFragment both viewmodels have correct values. - Background app with
Don't keep activities
to trigger process death and come back.
On SecondFragment both viewmodels contains correct value, even if you modify value on FirstFragment. - Press back to return on FirstFragment, Background app with
Don't keep activities
and open SecondFragment. On SecondFragment both viewmodels have correct values. - Background app with
Don't keep activities
to trigger process death and come back.
On SecondFragment first viewmodel doesn’t have restored value, second viewmodel has as expected.
Issue Analytics
- State:
- Created 3 years ago
- Reactions:7
- Comments:5 (2 by maintainers)
Top GitHub Comments
The root cause of the issue is that the
defaultViewModelProviderFactory
from an activity or fragment uses the activity itself as theSavedStateRegistryOwner
and that is different from theViewModelStoreOwner
used by theNavBackStack
. It seems these two should be the same, which is exactly what is going on with theHiltViewModelFactory
too, it uses the activity or fragment asSavedStateRegistryOwner
which is different from theViewModelStoreOwner
that is used by theViewModelProvider
by theNavBackStack
.We are investigating a solution but sadly I don’t have a workaround for now. We might either expose a builder / factory for
HiltViewModelFactory
(which is odd) or we might work with AndroidX itself to make it so that these two owners are in sync.Fixed by
hiltNavGraphViewModels
inhilt-navigation-fragment