ben
ben

Reputation: 3136

MvvmCross Android - Null Reference for ViewModel when Reloading Fragments

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:

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.

Upvotes: 3

Views: 3189

Answers (1)

Stuart
Stuart

Reputation: 66882

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:

  • to find some way to recreate your 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
  • to block the default Android fragment recreation (e.g. by stopping the parent 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 Fragments 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.

Upvotes: 6

Related Questions