xamarin.forms - 反应式 UI 数据持久性
问题描述
谁能帮助我就如何使用 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;
}
}
应用程序.cs
RxApp.SuspensionHost.CreateNewAppState = () => new AppBootstrapper();
RxApp.SuspensionHost.SetupDefaultSuspendResume(new
AkavacheSuspensionDriver<AppBootstrapper>());
MainPage = RxApp.SuspensionHost.GetAppState<AppBootstrapper>().CreateMainPage();
这里 MainPage 将尝试从缓存中检索“Something”,但它只是炸弹没有任何退出。我需要自己处理反序列化和数据处理吗?我期望首先创建默认的新 AppBootstrapper。
解决方案
所以我不确定我对此有何感受,但我找到了解决问题的方法。我发现 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
[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);
....
}
推荐阅读
- javascript - Jquery AJAX 请求正文为空。(Docker 内的 Django REST)
- json - 我无法在 PhpStorm 的 JSON 脚本标签中粘贴 Twig 代码
- xml - WS-Trust 1.3 规范与 xsd 的区别
- cordova - 将事件从 Native 发送到 Ionic
- java - 上下文:xml 中的属性占位符
- graphdb - 在 GraphDB 中为 Visual Graph 设置默认配置
- json - 将 XLS/CSV 转换为 JSON,不同的数据类型
- php - 访问 php 数组中的嵌套元素
- python - Python ctypes 设置 c_char_p 基础值
- visual-studio-code - VSCode:搜索所有项目内容