已阅读:3,098 次
Windows Phone 7 多任务机制剖析二:墓碑机制
ian | WP7 | 2011/10/28


由于WP7系统刚推出时并不支持多任务(即便是现在,第三方应用从前台切到后台之后也不能继续运行,关于后台任务,本文暂不讨论),为了达到程序切换时让用户觉得程序在后台继续运行的效果,WP7推出了墓碑机制,简单来说就是,在程序切到后台时将临时数据保存,然后当程序被切换回前台时将保存的数据读取恢复成离开时的场景再继续运行,这样用户就会觉得程序的运行没有被终止过。虽然墓碑机制对用户来说体验更好了,但是这需要开发人员在代码中对程序的逻辑做一些处理。

要了解墓碑机制,需要对WP7中应用程序的生命周期以及启动运行过程有一个清晰的了解:

1 程序启动
启动程序的方式很多,通常可以从系统的Tile图标或者是在第二屏中程序图标启动程序,此外也可通过点击推送的Toast消息或者通过Launchers 和 Choosers来启动程序。启动程序时会触发Application的Launching事件。

2 程序运行
程序从启动到运行后,进入第一个页面的:通过从配置文件WMAppManifest.xml获得要加载的第一个XAML页面,这个页面通常是由这句代码指定的:

1
<DefaultTask Name="_default" NavigationPage="MainPage.xaml" />

APP读取指定的XAML文件并生成新的Page实例,通过Frame(一个不可见的容器)显示出这个Page。程序在进入Page页面时会执行OnNavigatedTo方法。当这些完成后,程序才真正进入了运行状态。而OnNavigatedTo方法对于墓碑机制来说非常重要,我们一般在这个方法中进行一些数据恢复的操作。

3 休眠状态
当我们在程序中点击Win键回到桌面时,应用就会进入休眠状态,这个状态是在WP7.1中新加入的,是为了提升多个任务间的切换速度。

在程序进入休眠状态之前,会调用当前页面的OnNavigatedFrom方法,在这个方法中我们可以保存当前页面的一些数据状态;然后会触发Application中的Deactivated事件,在这个事件中,我们可以保存一些当前程序的数据。从这点来看,休眠状态和墓碑状态很相似,事实上也正是如此,对开发人员而言,墓碑状态基本上是一个透明的状态,不需要再过多的考虑它和休眠状态的区别,除了恢复墓碑数据时有一点小小的区别。

跟墓碑状态一样,休眠状态时,程序停止运行,但不同的是此时整个进程还是存在于内存中。当恢复这个程序时,就不需要创建一个新的实例。这样就加快了程序恢复和切换的速度,并且从休眠状态恢复时我们不需要去恢复墓碑数据。

当前台程序在运行过程中,内存不足或者不足以让程序流畅运行时,系统会执行一些操作来释放内存,此时程序就可能从休眠状态变换为的墓碑状态。

4 墓碑状态
在WP7版本中,程序没有休眠状态,因此程序被切到后台时就直接进入墓碑状态,这一点在WP7.1中有了改动,只有系统资源不够前台程序使用时,后台程序才可能从休眠状态进入到墓碑状态,这也是WP7.1相对于WP7.0最大的改进。一个程序进入到墓碑状态时,其进程被终止掉,但是程序的回退栈中的信息,以及我们保存的一些信息会保留在内存中。

5 程序恢复
当我们使用Back按钮或者长按Back从任务列表中返回程序,或者是从Launchers 或Choosers返回时,程序就会恢复执行,此时会调用当前Page的行OnNavigatedTo方法,我们一般把墓碑数据的回复操作放在这里执行。但是要注意一点,我们程序可能是从休眠状态,也可能是从墓碑状态返回的(虽然两者差别不大),如果是从休眠状态返回的话我们是不需要做任何数据恢复操作的,因为整个程序都还在内存中,并没有被重新初始化;而从墓碑状态序中返回,程序会初始化重新执行构造函数,我们就需要先恢复程序的状态和数据。

程序恢复时会触发Application类中的Activated 事件,我们可以通过检查IsApplicationInstancePreserved参数来判断程序是从休眠状态还是墓碑状态返回的,在此方法中我们可以用来恢复之前在Deactivated事件中保存的数据。

6 程序结束
在Windows Phone的中唯一退出程序的方法就是点击Back键,当Back Stack中不存在页面时程序就会退出。目前系统没有提供任何Exit方法来以代码的方式结束程序。在程序退出时会触发Application中的Closing事件,在这个事件中我们可以释放一些使用的资源,保存数据等等,要注意的是,如果一个程序从墓碑状态被结束,是不会触发此事件的。

墓碑数据的保存和恢复

在进入到墓碑状态时,数据会被保存到内存中,系统为我们提供了数据字典来保存我们的数据。 程序需要保存的数据一般分为两类,一个是程序全局的数据,我们可以存放到Application.State这个字典中,另一种是单个页面的私有数据,这类数据可以存放到Page.State的字典中。需要注意的是这些字典中存入的数据必须是可序列化的数据。另外我们也可以把数据保存到隔离存储区(Isolated Storage)中。

Application相关事件: Launching、Deactivated、Activated和Closing,我们可以在Deactivated和Activated中对系统的数据进行保存和恢复。
对每个页面而言,进入和离开页面时都会触发生的OnNavigatedTo和OnNavigatedFrom,我们在这里以用来保存和恢复页面的墓碑数据。
例如,在MainPage中实现墓碑数据的保存和恢复:

1
2
3
4
5
6
7
8
9
10
11
protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
{  
    base.OnNavigatedFrom(e);  
    State["num"] = num; //保存变量  
}  
 
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)  
{  
    base.OnNavigatedTo(e);  
    num = (int)State["num"]; //恢复变量  
}

当进入MainPage时,找到”num”这个墓碑数据恢复现场,而离开MainPage页面时,将num保存到字典中。这就是最简单的墓碑数据的保存与回复的过程。

程序需要针对墓碑/休眠状态、或者导航的具体形式做区别处理,这些可以通过如下方法实现:

WP7.1中开放了NavigationEventArgs 的NavigationMode属性,当我们新建一个页面进入时,此属性为New,而当我们从墓碑状态或其他页面返回时则是Back,很明显我们只有在Back时才需要恢复数据。而在OnNavigatedFrom方法中,当我们导航到新的页面时,此属性为New,而当我们回退到前一个页面时,此属性为Back。

当我们从休眠状态返回时,也会触发Application类中的Activated 事件,但是此时不需要进行数据恢复,WP7.1中新增了IsApplicationInstancePreserved属性来判断是休眠状态还是墓碑状态恢复的,如果了IsApplicationInstancePreserved为True,即是从墓碑状态启动时才需要恢复数据。

原创文章,转载请注明:转载自ian的个人博客[http://www.icodelogic.com]
本文链接地址: http://www.icodelogic.com/?p=246

tags:

没有评论

发表评论

你需要先 登录 才能回复