您的位置:首页 > 移动开发

【windows8开发】Metro App生命周期之Suspended与Resume

2012-09-06 16:45 381 查看
先来看这样一个场景:我们打开一个Metro程序,进行了一系列的编辑工作,突然想要查看另外一个Metro程序,然后ALT+TAB切换到这个App,确认完需要查看的内容后想切换回原来那个正在编辑的程序,突然发现那个程序已经被系统终止了,重新打开发现所有已编辑的东西都没了,于是大呼一声,“这是什么破系统.......”。
呵呵,其实这不是系统的问题,而是这个应用程序应该解决的问题,本文会讨论Metro程序的Suspended与Resume,看看如何解决以上问题,当然还会有一些关于Suspended与Resume的引申,希望对大家能有所帮助。本文代码都使用C#来表述。

曾经在其它文章中简单说明过,什么时候程序会被Suspended?一般来说都是由于使用者切换到了其他的Metro程序,当然如果当前设备电量不足等情况下,也会被Suspended。其实并不是Metro程序被切换后就马上会进入Suspended状态,系统会经过一定时间才会挂起此程序(大概10s左右),在挂起前如果又切回该程序,则程序会继续保持在Running状态。另外,我尝试了下,貌似从Metro程序切换回Metro桌面时,之前的Metro程序是不会被Suspended的。
再回到开始谈到的那个问题,为什么程序会被无故终止呢?由于Suspended的程序都还是保留在内存中,当此类程序过多时会占用系统很多资源,当系统内存资源紧张时,就会强制去关闭某些Suspended的程序,所以为了防止这种情况,一个稳定安全的程序即使被强制终止,也要求能够恢复Suspended之前的数据和一些程序状态(熟悉移动开发的朋友可能都知道,ios或者Android都有类似的特性)。但是,在系统强制关闭Suspended的程序时,是没有事件来通知程序的,所以我们只能在响应到Suspended事件即将被Suspended时来进行数据和状态的备份处理,看一段代码:


public sealed partial class MainPage : Page
{
     public MainPage()
     {
          this.InitializeComponent();
          Application.Current.Suspending += new SuspendingEventHandler(OnSuspending);

     }
     private void OnSuspending(object sender, SuspendingEventArgs e)
     {
               //TODO: Save application state and release exclusive resources
     }
}


从代码可以看到,可以通过Application的属性Suspending来绑定Suspended事件,如上代码所示,当程序被Suspended时,OnSuspended方法会被触发,我们可以在这里备份一些数据和状态,也可能需要释放一些占用的资源,比如关闭被打开的文件。WinRT提供了可供备份数据用的Storgae,我们可以用来按照Key-Vaule的形式保存我们希望的数据。

Windows.Storage.ApplicationDataContainer roamingSettings = Windows.Storage.ApplicationData.Current.RoamingSettings;
roamingSettings.Values["status"] = "app status";


但是需要注意的是,你必须再很短的事件内完成数据的备份工作,如果5s内没有完成处理,系统会认为被阻塞了而强制关闭该程序。
当程序在被Terminate之后又启动时,可以在App的OnLaunched方法中恢复之前的数据:
protected override void OnLaunched(LaunchActivatedEventArgs args)
{
     ......
     if (args.PreviousExecutionState == ApplicationExecutionState.Terminated)
     {
          //TODO: Load state from previously suspended application
          Windows.Storage.ApplicationDataContainer roamingSettings = Windows.Storage.ApplicationData.Current.RoamingSettings;
          string status = (string)roamingSettings.Values["status"];
     }
     ......


由于程序被Terminate了,所以又恢复时不会再触发Resume事件,而是触发OnLaunched。除了使用RoamingSettings外还可以使用LocalSettings来持久化数据,至于它们的区别会在后续其他文章中来介绍。还有,当你有一些处理不希望在程序被Suspended时打断时,就需要一些额外的考虑,比如播放音频,上传下载文件等。WinRT提供了一些API来完成这类功能,如BackgroundTransfer。
Suspended差不多讲完了,接着是Resume。其实大部分情况下,当Suspended的程序被重新Resume时是不需要做任何处理的,因为Suspended后程序还是都在内存中,不会丢失任何数据,Resume后也不需要执行额外的恢复工作。但是有些情况下,比如程序会跟Server建立Socket连接,当程序被Suspended后,长时间没有进行收发心跳包(heart
beats)时,服务器可能会断开连接,所以在Resume时需要在判断连接已断开后重新尝试去连接服务器恢复通信。这里介绍下如何响应Resume事件,跟Suspending事件类似,也是通过Application的Resuming来绑定Resume的事件,代码如下:
public sealed partial class MainPage : Page
{
    public MainPage()
    {
        this.InitializeComponent();
        Application.Current.Suspending += new SuspendingEventHandler(OnSuspending);
        Application.Current.Resuming += new EventHandler<Object>(OnResuming);
    }
    private void OnResuming(object sender, Object e)
    {
    }
	......

如果需要,我们可以再OnResuming方法中恢复网络连接等处理。

Suspended和Resume到这里介绍完了,下回会介绍Metro App的安装部署与卸载,希望大家继续捧场。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: