So I'm not sure how I feel about this, but I have found a solution to my problem. I discovered that the SuspensionHost does create the AppState eventually on its own. It then takes the stored data and re-hydrates whatever you were storing. To make use of this I had to do the following
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 }
});
}
}
So in the end the app will load, display a blank screen, and then the Suspension Host will create a new AppBootloader, populate the stored data, and update the AppState. Using this new app state I can then set the MainPage.
In the AppBootLoader I am only saving the following as a 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??
}
}
}
And Finally the Class that I am saving
public class NavStackPersistence
{
public string Name { get; set; }
public string Path { get; set; }
public LoginViewModel ViewModel { get; set; }
}
This will successfully Load an AppBootloader, populate the NavStack with a collection, and each item in that collection (right now only a loginViewModel) will also be Initialized and Re-Hydrated. My example here does Provide a Name and a fully populated LoginViewModel that when it is navigated to will still retain the LoginName and Password that was used.
Anyone on the ReactiveUI team have any comments on how this is implemented? Is there a better way to approach this?
BTW. Anyone looking to use this for UWP in xamarin, I had to add this to the UWP App.CS class file.
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);
....
}