Сохранение данных реактивного пользовательского интерфейса

Может ли кто-нибудь помочь мне с каким-либо руководством о том, как реализовать сохраняемость данных в приложении форм Xamarin с использованием UWP и iOS? Я нашел несколько примеров в Интернете, но они довольно старые и ссылаются только на iOS и Android Xamarin Native. В основном я хочу взять модель просмотра текущей страницы и сохранить все данные, введенные пользователем.

AkavacheПодвескаВодитель

namespace NameSpace    {
public class AkavacheSuspensionDriver<TAppState> : ISuspensionDriver where TAppState : class
{
    private const string appStateKey = "AppBootstrapper";

    public IObservable<Unit> InvalidateState()
    {
        var result = BlobCache.UserAccount.InvalidateObject<TAppState>(appStateKey);
        return result;
    }

    public IObservable<object> LoadState()
    {
        var result = BlobCache.UserAccount.GetObject<TAppState>(appStateKey);
        return result;
    }

    public IObservable<Unit> SaveState(object state)
    {
        var result = BlobCache.UserAccount.InsertObject(appStateKey, (TAppState)state);
        return result;
    }
}

App.cs

 RxApp.SuspensionHost.CreateNewAppState = () => new AppBootstrapper();
 RxApp.SuspensionHost.SetupDefaultSuspendResume(new 
 AkavacheSuspensionDriver<AppBootstrapper>());

 MainPage = RxApp.SuspensionHost.GetAppState<AppBootstrapper>().CreateMainPage();

Здесь MainPage попытается извлечь «Что-то» из кеша, но просто бомбит, ничего не выходит. Нужно ли мне самому заниматься десериализацией и обработкой данных? Я ожидал, что сначала будет создан новый AppBootstrapper по умолчанию.


person Joe Harvey    schedule 14.12.2018    source источник


Ответы (2)


Там много разных решений. Одним из них может быть проект ReactiveUI под названием akavache. Это позволит вам сохранить ваши данные. Вы можете смешивать их с AutoSuspendHelper https://reactiveui.net/docs/handbook/data-persistence/

Имейте в виду, что наша документация по сохранению данных в данный момент находится в стадии разработки. Мы пытаемся удалить все разговоры в чате из нашей документации.

person Glenn Watson    schedule 14.12.2018
comment
Да, я прочитал руководство и смог реализовать хранилище данных и поиск. Но я не уверен, что мне делать с AkavacheSuspensionDriver. Позвольте мне опубликовать и пример ниже - person Joe Harvey; 14.12.2018

Поэтому я не уверен, как я к этому отношусь, но я нашел решение своей проблемы. Я обнаружил, что SuspensionHost в конечном итоге сам создает AppState. Затем он берет сохраненные данные и повторно гидратирует все, что вы хранили. Чтобы использовать это, мне пришлось сделать следующее

    public App()
    {
        InitializeComponent();
        try
        {
            RxApp.SuspensionHost.CreateNewAppState = () =>
            {
                return new AppBootstrapper();
            };

            RxApp.SuspensionHost.SetupDefaultSuspendResume(new AkavacheSuspensionDriver<AppBootstrapper>());

            RxApp.SuspensionHost.ObserveAppState<AppBootstrapper>().Subscribe<AppBootstrapper>((a) =>
            {
                Xamarin.Forms.Device.BeginInvokeOnMainThread(() =>
                {
                    var bootstrapper = a;
                    MainPage = bootstrapper.CreateMainPage();
                });
            });

            AppCenterLog.Info("Start", "Application Started");
        }
        catch (Exception ex)
        {
            //Crash reporting not available in appcenter - using event analytics as temp solution
            Analytics.TrackEvent("Bootstrap Runtime Error", new Dictionary<string, string> {
                { "Exception", ex.Message }
            });
        }
    }

Таким образом, в конце приложение загрузится, отобразит пустой экран, а затем узел подвески создаст новый загрузчик приложений, заполнит сохраненные данные и обновит AppState. Используя это новое состояние приложения, я могу установить MainPage.

В AppBootLoader я сохраняю только следующее как Datamember

    [DataMember]
    public ICollection<NavStackPersistence> NavStack
    {
        get
        {
            ICollection<NavStackPersistence> navStack = new List<NavStackPersistence>();
            foreach (var vm in Router.NavStackPersistence)
            {
                navStack.Add(new NavStackPersistence()
                {
                    Path = vm.UrlPathSegment,
                    Name = vm.ToString(),
                    ViewModel = (LoginViewModel)vm
                });
            }

            return navStack;
        }

        set
        {
            if (value != null)
            {
                foreach (var vm in value)
                {
                    this.Router
                       .NavigateAndReset
                       .Execute(vm.ViewModel)
                       .Subscribe();
                }
                // TODO in here we set the router path??
            }
        }
    }

И, наконец, класс, который я сохраняю

public class NavStackPersistence
{
    public string Name { get; set; }
    public string Path { get; set; }
    public LoginViewModel ViewModel { get; set; }
}

Это успешно загрузит AppBootloader, заполнит NavStack коллекцией, и каждый элемент в этой коллекции (сейчас только loginViewModel) также будет инициализирован и повторно гидратирован. В моем примере здесь указано имя и полностью заполненная модель LoginViewModel, которая при переходе к ней по-прежнему сохраняет использованные имя пользователя и пароль.

У кого-нибудь из команды ReactiveUI есть какие-либо комментарии о том, как это реализовано? Есть ли лучший способ подойти к этому?

КСТАТИ. Любой, кто хочет использовать это для UWP в xamarin, должен был добавить это в файл класса UWP App.CS.

    private AutoSuspendHelper autoSuspendHelper;

    /// <summary>
    /// Initializes the singleton application object.  This is the first line of authored code
    /// executed, and as such is the logical equivalent of main() or WinMain().
    /// </summary>
    public App()
    {
        autoSuspendHelper = new AutoSuspendHelper(this);
        this.InitializeComponent();
        this.Suspending += OnSuspending;
    }

    /// <summary>
    /// Invoked when the application is launched normally by the end user.  Other entry points
    /// will be used such as when the application is launched to open a specific file.
    /// </summary>
    /// <param name="args">Details about the launch request and process.</param>
    protected override void OnLaunched(LaunchActivatedEventArgs args)
    {
        autoSuspendHelper.OnLaunched(args);

        ....
    }
person Joe Harvey    schedule 14.12.2018