Source code - https://github.com/benhysell/V.FlyoutTest/
Issue - While intermixing fragments and base views and using the settings on the device - "Developer Options / Don't keep Activities" ViewModels are null if OnDestory() is called and then the activity is brought back into view. This results in a null reference exception and app crash.
Description I have a slideout/hamburger menu in Android using MvvmCross. On application start the following steps take place:
Message is received in the EnterTimeViewModel, normally here we'd do some sort of checking to see if we are logged in or not, but in this case we just call ShowViewModel with LoginViewModel to simulate a log in request and prompt for the user.
LoginViewModel is not a fragement, just a normal base view. It is shown to the user
The sequence of events with regards to MvvmCross transitions is as follows while loading and unloading HomeView:
Login Screen is shown, after login
It feels like a few steps are skipped, resulting in the crash. Ideas? Places to go looking?
As a point of reference, the project I based my sliding menu on, https://github.com/jamesmontemagno/Xam.NavDrawer exhibits the same issue.
Update Implemented a fix http://benjaminhysell.com/archive/2014/06/mvvmcross-flyoutnavigation-hamburger-menu-sliding-menu-for-android-null-reference-exception-on-fragment-shown-fix/, tldr - took responsibility to try and save the ViewModels, and worst case re-create them if the fragment is unloaded from memory.
From your code, it looks like you are manually setting the ViewModel's of your fragments when you first create them:
frag.ViewModel = viewModelLocal;
from https://github.com/benhysell/V.FlyoutTest/blob/master/V.FlyoutTest.Droid/Views/HomeView.cs#L153
When your hosting Activity
is torn down because of "Don't keep Activities" and then shown again, then Android will save the fragment state in the instanceState bundle, and it will try to recreate those fragments - which (I guess) is when you are seeing your NullReferenceException
.
To work around this you will need either:
ViewModel
during OnCreateView
when the bundle
is present. You could do this using serialisation/deserialisation techniques or by moving the ViewModel=viewModelLocal
code inside your OnCreateView method instead of inside the owning Activity
bundle
from using its OnCreate
bundle
and using your own reinflation logic)Note: this behaviour doesn't happen for Activity
as MvvmCross can reuse the Intent
there in order to recreate the ViewModel for the Activity. But for Fragment
s the app has taken responsibility for creating these (in its custom presenter), so currently the app also has to take responsibility to recreate the ViewModel
too.