Жизненный цикл ViewModel MvvmCross во время вращения

Я использую Mvvmcross для разработки приложения для Android. Я имею дело с проблемой жизненного цикла ViewModel во время ротации. Кажется, что обычно ViewModel сохраняется во время вращения. Однако это не так, когда я представляю ViewModels в MvxTabActivity. Когда происходит вращение, он всегда вызывает конструктор ViewModel.

Я использовал аналогичную структуру кода, как в учебнике N+1 https://github.com/slodge/NPlus1DaysOfMvvmCross/tree/master/N-25-Tabbed.

есть ли способ изменить этот учебник, чтобы сохранить ViewModels в памяти во время вращения при использовании MvxTabActivity?

1 ответов


кэширование ViewModel по умолчанию, которое пытается обойти поведение вращения Android, основано на IMvxSingleViewModelCache - поэтому неудивительно, что он не может справиться с несколькими действиями и несколькими моделями просмотра.

для того, где этот интерфейс объявлен и используется, см. https://github.com/slodge/MvvmCross/search?q=IMvxSingleViewModelCache&ref=cmdform

если это поведение беспокоит вас, то вы должны быть в состоянии обойти его одним из :

1. Используйте вкладки на основе фрагментов, а не на основе активности

Android обрабатывает жизненный цикл фрагмента по-разному для активности.

2. Или продолжайте использовать вкладки на основе активности, но реализуйте свой собственный IMvxSingleViewModelCache

это должно быть просто, например, чтобы идентифицировать ваши дочерние модели представления с их "дочерним" соглашением об именах.

после этого вы можете реализовать что-то вроде:

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;
    }
}

этого класса on MvxSingleViewModelCache.cs С одним небольшим добавлением.

вы можете зарегистрировать экземпляр этого класса как IMvxSingleViewModelCache синглтон в InitializeLastChance настройки вашей системы.

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

после этого активность home / tab должна (я думаю) продолжать работать - и она передаст viewmodels вниз на вкладку children после вращения.

(другие возможности IMvxSingleViewModelCache возможны-например, он может кэшировать несколько моделей просмотра - но, пожалуйста, не пусть он кэширует слишком много моделей просмотра слишком долго или вы можете столкнуться с условиями "из памяти")

3. Или выключите обработку вращения Android

если добавить android:configChanges="orientation" флаг (или его эквивалент атрибута monodroid), то вы можете просто регулируют вращение себя.