MvvmCross ViewModel Lifecycle During Rotation

I am using Mvvmcross to develop an Android application. I am dealing with a ViewModel lifecycle issue during rotation. It seems that the ViewModel as a whole is preserved during rotation. However, this is not the case when I present ViewModels in MvxTabActivity. When a rotation occurs, it always invokes the ViewModel constructor.

I used the same code structure as in the N + 1 tutorial https://github.com/slodge/NPlus1DaysOfMvvmCross/tree/master/N-25-Tabbed .

Is there a way to modify this tutorial to keep ViewModels in memory during rotation when using MvxTabActivity?

+6
source share
1 answer

The default ViewModel caching, which attempts to circumvent Android rotation behavior, is based on IMvxSingleViewModelCache - so it’s not too surprising that it cannot handle multiple actions and multiple view modes.

Here, where this interface is declared and used, see https://github.com/slodge/MvvmCross/search?q=IMvxSingleViewModelCache&ref=cmdform

If this behavior bothers you, you should be able to get around it with one of:

1. Use tabs based on fragments, not based on actions

Android handles the fragment life cycle differently for Activity.

2. Or continue to use activity-based tabs, but make your own IMvxSingleViewModelCache

It should be simple, for example, to identify the models of your child view using their "Child" naming convention.

After that, you can implement something like:

 public class MyCustomViewModelCache : IMvxSingleViewModelCache { private const string BundleCacheKey = "__mvxVMCacheKey"; private int _counter; private IMvxViewModel _currentViewModel; public void Cache(IMvxViewModel toCache, Bundle bundle) { if (toCache != null && toCache.GetType().Name.StartsWith("Child")) { // don't worry about caching child view models return; } _currentViewModel = toCache; _counter++; if (_currentViewModel == null) { return; } bundle.PutInt(BundleCacheKey, _counter); } public IMvxViewModel GetAndClear(Bundle bundle) { var storedViewModel = _currentViewModel; _currentViewModel = null; if (bundle == null) return null; var key = bundle.GetInt(BundleCacheKey); var toReturn = (key == _counter) ? storedViewModel : null; return toReturn; } } 

This class is based on MvxSingleViewModelCache.cs with just one small addition.

You can register an instance of this class as IMvxSingleViewModelCache singleton during InitializeLastChance your installation.

  Mvx.RegisterSingleton<IMvxSingleViewModelCache>(new MyCustomViewModelCache()); 

In this case, the home / tab action should (I think) continue to work - and it will transmit viewmodels to the children of the tab after rotation.

(Other possibilities are possible for IMvxSingleViewModelCache - for example, it can cache several view models), but please do not let too many view models cache too much or you may run into "out of memory")

3. Or turn off Android rotation processing

If you add the android:configChanges="orientation" flag (or its equivalent equivalent to a monodroid), you can simply handle the rotation yourself.

+4
source

Source: https://habr.com/ru/post/948845/


All Articles