【问题标题】:Reactive UI Data Persistence反应式 UI 数据持久性
【发布时间】:2019-05-15 21:17:15
【问题描述】:

谁能帮助我就如何使用 UWP 和 iOS 在 Xamarin 表单应用程序上实现数据持久性提供一些指导?我在网上找到了一些示例,但它们相当古老,仅参考 iOS 和 Android Xamarin Native。基本上我想获取当前页面的视图模型并保留所有用户输入的数据。

AkavacheSuspensionDriver

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。

【问题讨论】:

    标签: xamarin.forms reactiveui xamarin.uwp data-persistence datapersistance


    【解决方案1】:

    有很多不同的解决方案。一个是名为 akavache 的 ReactiveUI 项目。它将允许您保留数据。您可以将它们与 AutoSuspendHelper https://reactiveui.net/docs/handbook/data-persistence/

    混合使用

    请注意,我们关于数据持久性的文档目前正在进行中。我们正在尝试从我们的文档中删除所有聊天对话。

    【讨论】:

    • 是的,我已经阅读了手册并且能够实现一些数据存储和检索。但我不确定我应该用 AkavacheSuspensionDriver 做什么。让我在下面发布和示例
    【解决方案2】:

    所以我不确定我对此有何感受,但我找到了解决问题的方法。我发现 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 }
                });
            }
        }
    

    所以最终应用会加载,显示一个空白屏幕,然后 Suspension Host 将创建一个新的 AppBootloader,填充存储的数据,并更新 AppState。使用这个新的应用程序状态,我可以设置 MainPage。

    在 AppBootLoader 中,我只将以下内容保存为数据成员

        [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,当它被导航到时仍将保留使用的 LoginName 和 Password。

    ReactiveUI 团队中的任何人都知道这是如何实现的吗?有没有更好的方法来解决这个问题?

    顺便说一句。任何想在 xamarin 中将其用于 UWP 的人,我都必须将其添加到 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);
    
            ....
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-12-23
      • 2016-09-24
      • 1970-01-01
      • 2011-04-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多