Metro App中关于挂起与恢复的操作
Windows 8 应用通常涉及到两种数据类型:应用数据与会话数据。这篇主要讲解会话层面,会话层的数据是基于用户每次使用应用而形成,这些数据可能不需要留存在设备中。在整个应用生命周期中,应用启动后便进入运行状态。当用户离开或系统进入待机状态时,应用会进入挂起状态,此时应用将被放入到内存中,待用户重新使用时便会恢复成运行状态。
接下来,我们主要来实现如何在挂起时,实现数据的保存。
新建项目中,添加一个基本页面,不能添加空白页面,因为在添加基本页面时,项目中会自动添加几个文件,这些文件存放在Common文件夹下:
这里主要用到的是LayoutAwarePage.cs(用于导航和进程生命期管理的状态管理)和SuspensionManager.cs(捕获全局会话状态以简化应用程序的进程生命期管理)文件。
1.接下来我们将进行应用挂起处理。
1)打开App.xaml.cs 程序,在OnLaunched 方法中创建了rootFrame,当rootFrame 为Null 时将重新创建Frame,在这个逻辑判断中要使用SuspensionManager.RegisterFrame 方法进行rootFrame 注册,这样才可以使应用获得根Frame 信息并进行数据存储。
protected async override void OnLaunched(LaunchActivatedEventArgs args)
{
Frame rootFrame = Window.Current.Content as Frame;
// 不要在窗口已包含内容时重复应用程序初始化,
// 只需确保窗口处于活动状态
if (rootFrame == null)
{
// 创建要充当导航上下文的框架,并导航到第一页
rootFrame = new Frame();
SuspensionManager.RegisterFrame(rootFrame, "appFrame");
if (args.PreviousExecutionState == ApplicationExecutionState.Terminated)
{
//TODO: 从之前挂起的应用程序加载状态
}
// 将框架放在当前窗口中
Window.Current.Content = rootFrame;
}
if (rootFrame.Content == null)
{
// 当未还原导航堆栈时,导航到第一页,
// 并通过将所需信息作为导航参数传入来配置
if (!rootFrame.Navigate(typeof(Mainpage)))
{
throw new Exception("Failed to create initial page");
}
}
// 确保当前窗口处于活动状态
Window.Current.Content = rootFrame;
Window.Current.Activate();
}
注意:红色代码处是给当前的Frame注册挂起事件,这里只是给一个页面的Frame注册事件,我们可以给多个页面注册
2) 在OnSuspending 方法中,使用SuspensionManager.SaveAsync 方法将挂起应用的当前状态进行保存,这里可以调用异步操作来进行处理。
/// <summary>
/// 在将要挂起应用程序执行时调用。在不知道应用程序
/// 将被终止还是恢复的情况下保存应用程序状态,
/// 并让内存内容保持不变。
/// </summary>
/// <param name="sender">挂起的请求的源。</param>
/// <param name="e">有关挂起的请求的详细信息。</param>
private async void OnSuspending(object sender, SuspendingEventArgs e)
{
//App.xaml.cs 文件包含 Application.Suspending 事件的处理程序。Windows 即将挂起应用时会调用此事件处理程序。
//这是我们保存应用状态以防该应用被终止的时机。我们使用 SuspensionManager 类来简化会话状态保存过程。
//该类会保存应用的导航状态并为你提供保存活动页面会话状态的机会。
var deferral = e.SuspendingOperation.GetDeferral();
//TODO: 保存应用程序状态并停止任何后台活动
await SuspensionManager.SaveAsync(); //调用 SaveAsync 可保存 Frame 的导航状态,
//然后为 Page 提供保存其内容的机会。
deferral.Complete();
}
注意:当用户挂起应用时,程序会进入此方法里, 然后运行上面红色的代码,接下来会进入系统处理挂起操作,紧接着会调用页面中的SaveState方法,处理需要保存的数据。
3)打开MainPage.xaml.cs ,添加SaveState方法,添加如下代码,作用是用与挂起时能将当前的用户名字段保存起来。
protected override void SaveState(Dictionary<String, Object> pageState)
{
pageState["show"] = this.show.Text;
}
到此,以上就是将会话层的数据在应用挂起时,将数据保存起来,这里只是保存简单的string类型数据,如果需要保存更为复杂的类型,这里还需要进一步修改,请参见下一篇文章。
2.恢复操作
1)挂起操作完成后,就要进行恢复操作,将暂存的数据恢复到应用中。再次打开App.xaml.cs 在OnLaunched 方法中的PreviousExecutionState 判断为Terminated 时加入SuspensionManager.RestoreAsync 方法恢复以前的应用状态。
protected async override void OnLaunched(LaunchActivatedEventArgs args)
{
Frame rootFrame = Window.Current.Content as Frame;
if (rootFrame == null)
{
rootFrame = new Frame();
SuspensionManager.RegisterFrame(rootFrame, "appFrame");
if (args.PreviousExecutionState == ApplicationExecutionState.Terminated)
{
//TODO: 从之前挂起的应用程序加载状态
SuspensionManager.RestoreAsync();
}
// 将框架放在当前窗口中
Window.Current.Content = rootFrame;
}
if (rootFrame.Content == null)
{
if (!rootFrame.Navigate(typeof(Mainpage)))
{
throw new Exception("Failed to create initial page");
}
}
// 确保当前窗口处于活动状态
Window.Current.Content = rootFrame;
Window.Current.Activate();
}
2)在MainPage.xaml.cs 中添加LoadState方法,代码如下所示:
/// <summary>
/// 使用在导航过程中传递的内容填充页。在从以前的会话
/// 重新创建页时,也会提供任何已保存状态。
/// </summary>
/// <param name="navigationParameter">最初请求此页时传递给
/// <see cref="Frame.Navigate(Type, Object)"/> 的参数值。
/// </param>
/// <param name="pageState">此页在以前会话期间保留的状态
/// 字典。首次访问页面时为 null。</param>
protected override void LoadState(Object navigationParameter, Dictionary<String, Object> pageState)
{
if (pageState!= null&&pageState.ContainsKey("show"))
{
this.show.Text = pageState["show"].ToString();
}
}
这里需要注意的是,如果页面MainPage.xaml.cs 中有OnNavigatedTo方法,并且你重写了此方法,你需要自己在将LoadState引用进来,不然会出错误。因为如果没有重写OnNavigatedTo方法,系统会调用MainPage父类的OnNavigatedTo方法,在此方法中会引用LoadState方法。或者添加如下代码页可以。
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
}
另外在App.xaml.cs文件中:
public App()
{
this.InitializeComponent();
this.Suspending += OnSuspending;
this.Resuming += OnResuming;
}
红色代码处是添加恢复时的事件,当我们从挂起变成恢复时,会首先进入OnResuming事件中,在此事件中可以进行处理保存的数据,然后在传入的页面中。