在Windows Phone上运行的应用程序从开始到程序运行结束,其整个生命周期都是由Windows phone的执行模型所支配。执行模型被设计的目的就是为终端用户实时提供快速的、反应灵敏的体验。为了实现这样的初衷,Windows Phone仅仅允许在前台运行一个第三方应用程序(7.0中)——即与用户进行交互的可见的当前应用程序。这样做就消除了用户在其移动终端设备后台上运行多个应用程序而导致的程序间竞争有限的系统资源,而使用户的移动终端设备处于较低的性能和电池电量急剧减少的可能性。
在生命周期中,下面的几个事件是非常重要到:
App.xaml.cs:Application_Launching
App.xaml.cs:Application_Closing
App.xaml.cs:Application_Deactivated
App.xaml.cs:Application_Activated
Page.cs:OnNavigatedFrom:离开当前页面时(不要弄反了)
Page.cs:OnNavigatedTo:进入当前页面时
1、一般生命周期
这里说的一般生命周期指的是没有被中断的生命周期,经历了程序启动(Application_Launching)——进入主页面(OnNavigatedTo)——离开主页面(OnNavigationFrom)——程序直接通过BACK键关闭(Application_Closing)
1、应用程序第一次启动(首页Tile或应用列表中启动)就开启一个进程,产生应用程序实例,然后就调用Launching事件,在这里你可以做一些程序初始化的准备工作,但不要做太耗时的工作,比如读取文件或者说是调用服务器端数据等,因为在这里页面还没有加载,避免用户误以为软件Bug或是其他异常。还有就是微软的10s规则,如果在10s还没有启动,系统将会直接关闭程序。
2、第一个界面出来了,进入Running状态。如果你按下return按钮,会引发回退,因为它前面已经没有页面回退,因此它会引发了Closeing事件,关闭程序。
这个过程触发了四个事件:依次是:Launching、OnNavigatedTo、OnNavigatedFrom、Closing。
2、墓碑化(TombStone)生命周期
程序被中断(包括屏幕锁、呼入电话、短信息、提醒功能、低电量、程序切换、用户点击开始按钮等),进入墓碑化状态的生命周期,经历了程序启动(Application_Launching)----进入主页面(OnNavigatedTo)----离开主页面(OnNavigationFrom)----进入墓碑状态(Application_Deactivated)----从墓碑中恢复(Application_Activated)----进入主页面(OnNavigatedTo)----离开主页面(OnNavigationFrom)----程序直接通过BACK键关闭(Application_Closing)。
注意:并不是所有的应用程序进入墓碑化之后都会被Activated。比如用户运行程序时点击开始按钮进入墓碑化状态,但是又从程序列表或者开始界面点击程序图标进入程序,此时并不调用Activated事件,而是直接启动,调用Launching,产生一个新的应用程序实例。只有当用户完成其他的任务,通过back按钮返回应用程序,才会Activated。
代码示例
app.xaml.cs
private void Application_Launching(object sender, LaunchingEventArgs e)
{
Debug.WriteLine("TOMBSTONE:Application_Launching at {0}" + DateTime.Now.ToLongTimeString());
}
// 激活应用程序(置于前台)时执行的代码
// 此代码在首次启动应用程序时不执行
private void Application_Activated(object sender, ActivatedEventArgs e)
{
Debug.WriteLine("TOMBSTONE:Application_Activated at {0}" + DateTime.Now.ToLongTimeString());
}
// 停用应用程序(发送到后台)时执行的代码
// 此代码在应用程序关闭时不执行
private void Application_Deactivated(object sender, DeactivatedEventArgs e)
{
Debug.WriteLine("TOMBSTONE:Application_Deactivated at {0}" + DateTime.Now.ToLongTimeString());
}
// 应用程序关闭(例如,用户点击“后退”)时执行的代码
// 此代码在停用应用程序时不执行
private void Application_Closing(object sender, ClosingEventArgs e)
{
Debug.WriteLine("TOMBSTONE:Application_Closing at {0}" + DateTime.Now.ToLongTimeString());
}
MainPage.xaml.cs
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
Debug.WriteLine("TOMBSTONE:OnNavigatedTo at {0}" + DateTime.Now.ToLongTimeString());
}
protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
{
Debug.WriteLine("TOMBSTONE:OnNavigatedFrom at {0}" + DateTime.Now.ToLongTimeString());
}
输出结果:
TOMBSTONE:Application_Launching at {0}21:47:49
TOMBSTONE:OnNavigatedTo at {0}21:47:49
TOMBSTONE:OnNavigatedFrom at {0}21:48:45
“UI Task”(托管): 已加载“System.Runtime.Serialization.dll”
TOMBSTONE:Application_Deactivated at {0}21:48:46
TOMBSTONE:Application_Activated at {0}21:49:01
TOMBSTONE:OnNavigatedTo at {0}21:49:01
TOMBSTONE:OnNavigatedFrom at {0}21:49:18
TOMBSTONE:Application_Closing at {0}21:49:18
现在我们再重新看看那六个事件,每个事件应该做哪些工作:
(1)Launching:执行非常少量的代码,不要执行资源密集型操作,一般为从Isolated Storage中加载一些永久配置数据(persisted data)。应用程序不应该试图从以前的应用程 序实例中恢复瞬时状态。当用户启动一个应用程序,就出现了一个新的应用程序实例。
using (IsolatedStorageFile Iso = IsolatedStorageFile.GetUserStoreForApplication())
{
if(IsolatedStorageSettings.ApplicationSettings.Contains(IsoSetting1))
{
IsoContext = IsolatedStorageSettings.ApplicationSettings[IsoSetting1] as string;
}
}
(2)Closing: 处理关闭事件,应用程序应该把所有的持久化数据保存到独立的存储中。此时没有必要保存瞬时状态数据,即那些只和前应用程序实例相关的数据。
using (IsolatedStorageFile Iso = IsolatedStorageFile.GetUserStoreForApplication())
{
IsolatedStorageSettings.ApplicationSettings[IsoSetting1] = IsoContext;
}
(3)Deactivated:使用PhoneApplicationService.State保存一些临时数据(transient data)。 在状态信息词典中存储的数据是瞬时状态数据或者是能帮助应用程序在被禁止时恢复其状态的数据。由于并不能保证一个被禁止的应用程序会被重新激活,所以在此事件的处理中应用程序需要把永久配置数据保存到独立存储空间。
PhoneApplicationService.Current.State[IsoSetting1] = IsoContext;
(4)Activated:从PhoneApplicationService.State读取一些临时数据,恢复到用户离开此页面的状态,保持用户体验的一致性。
IsoContext = PhoneApplicationService.Current.State[IsoSetting1] as string;
(5)OnNavigatedFrom:保存一些页面级的信息,使用PhoneApplicationPage.State来保存信息。
base.OnNavigatedFrom(e);
if (e.NavigationMode != System.Windows.Navigation.NavigationMode.Back)
{
State[numsetting1] = num;
}
(6)OnNavigatedFTo:从PhoneApplicationPage.State中读取数据,回复页面状态,让用户看到和原先一摸一样的页面(包括光标位置、ScrollViewer的位置、DeepZoom的图片大小)。
base.OnNavigatedTo(e);
if (e.NavigationMode != System.Windows.Navigation.NavigationMode.New)
{
if (State.ContainsKey(numsetting))
{
num = State[numsetting] as string;
}
}
最后总结下整个生命周期:
本节讨论 Windows Phone 应用程序的所有应用程序生命周期元素,并重点介绍每个步骤中应用程序应采取的操作。本节提供了操作系统和用户触发各种应用程序状态更改的背景。有关事件及应用程序应执行的操作的简化清单,请参阅执行模型事件和应用程序操作摘要。
Launching 事件
Launching 事件在用户从已安装程序列表或从“开始”中的磁贴或通过其他方式(如点按与应用程序相关的 Toast 通知或从“Photos Extras”菜单中选择应用程序)启动新的应用程序实例时引发。当以此方式启动应用程序时,它应向用户显示新实例,而不是先前实例的延续。为了帮助确保应用程序快速加载,应在该事件的处理程序中执行尽可能少的代码。特别是,避免文件和网络操作等资源密集型任务。您应在应用程序加载之后,在后台线程中执行这些任务以便实现最佳的用户体验。
运行
启动之后,应用程序处于运行状态。在用户向前导航、离开应用程序或向后导航到第一个应用程序页面之前,应用程序程序将持续运行。Windows Phone 应用程序不应为用户提供退出应用程序的机制。当手机的锁定屏幕功能启动时,应用程序将保持运行状态,除非您已禁用应用程序空闲检测。有关更多信息,请参阅 Windows Phone 空闲检测。
OnNavigatedFrom 方法
当用户导航离开应用程序页面时,将会调用 OnNavigatedFrom(NavigationEventArgs) 方法。这可能是由应用程序中的普通页面导航导致。当取消激活应用程序时也会调用该方法,下一节将对此进行讨论。每当调用该方法时,应用程序都应存储页面的状态,以便在用户返回到页面时可以还原应用程序。向后导航除外。可以使用 NavigationMode 属性来确定导航是否为向后导航,若为向后导航,则无需保存状态,因为页面将在下次访问时重新创建。
在某些情况下,您可能希望将状态同时保存在 OnNavigatingFrom(NavigatingCancelEventArgs) 方法中。尤其是在存储 MediaElement 控件的状态时,您将需要执行此操作。
Deactivated 事件
当用户向前导航、导航出您的应用程序、按“开始”按钮或启动其他应用程序时,都将会引发 Deactivated 事件。如果您的应用程序启动选择器,也会引发 Deactivated 事件。有关选择器的更多信息,请参阅 Windows Phone 启动器和选择器概述。当设备的锁定屏幕功能启动时,也会引发该事件,除非已禁用应用程序空闲检测。
在 Deactivated 事件的处理程序中,您的应用程序应保存任何应用程序状态,以便将来还原。Windows Phone 应用程序随 State 对象一起提供,后者是可以用来存储应用程序状态的字典。如果应用程序在被逻辑删除后重新激活,则将使用您保存在 Deactivated 中的数据填充该状态字典。由于内存中存在该数据,您可以用它来还原状态,而无需资源密集型的文件操作。
在调用 Deactivated 后,应用程序可能会被完全终止。当应用程序终止时,其状态将不保留。因此,还应在 Deactivated 事件期间,将应用程序实例间应保留的所有未保存状态存储到独立存储中。
休眠
当用户向前导航或导航出应用程序时,引发 Deactivated 事件后,操作系统将尝试使应用程序置于休眠状态。在此状态下,应用程序的所有线程均将停止,并且不进行任何处理操作,但应用程序仍完好地保留在内存中。如果从该状态中重新激活应用程序,应用程序无需重新创建任何状态,因为状态已保留。
如果在应用程序进入休眠状态后启动新的应用程序,这些应用程序需要更多的内存才能提供出色的用户体验,操作系统将开始逻辑删除休眠的应用程序以释放内存。
已逻辑删除
逻辑删除的应用程序已终止,但该应用程序的导航状态相关信息和 Deactivated 期间由应用程序填充的状态字典将保留下来。设备每次最多可维护五个应用程序的逻辑删除信息。如果在逻辑删除应用程序之后,用户向后导航至应用程序,则应用程序将会重新启动并使用保留的数据还原状态。否则,将只是终止应用程序。
Activated 事件
当用户返回到休眠或逻辑删除的应用程序时,将调用 Activated 事件。应用程序应检查事件参数的 IsApplicationInstancePreserved 属性,以确定应用程序是从休眠状态返回,还是从逻辑删除状态返回。如果 IsApplicationInstancePreserved 为 true,则应用程序之前处于休眠状态,状态已由操作系统自动保留。若为 false,则应用程序之前已被逻辑删除,应用程序应使用状态字典来还原应用程序状态。在执行 Activated 事件处理程序期间,应用程序不应执行资源密集型任务(例如,从独立存储或网络资源加载内容),因为这会增加应用程序恢复所用的时间。而是应在加载应用程序之后,在后台线程中执行这些操作。
OnNavigatedTo 方法
当用户导航到页面时,即会调用 OnNavigatedTo(NavigationEventArgs) 方法。这包括当应用程序第一次启动时、用户在应用程序的页面之间进行导航时以及在应用程序休眠或被逻辑删除后重新启动时。在此方法中,应用程序应检查是否页面为新实例。若不是新实例,则无需还原。若页面为新实例,并且在页面的状态字典中存在数据,则应使用该数据来还原页面 UI 的状态。
Closing 事件
当用户向后导航到应用程序的第一页时,即会引发 Closing 事件。在这种情况下,应用程序将终止,并且不会保存状态。在 Closing 事件处理程序中,您的应用程序可以保存应跨实例保留的数据。应用程序完成所有应用程序和页面导航事件的时间被限定为 10 秒。若超出此限度,则应用程序将终止。因此,最好保存整个应用程序生存期的持续状态,避免在 Closing 事件处理程序中执行大量的文件 I/O 操作。
下表是应用程序生命周期内所发生事件和应用程序应针对每个事件执行的操作的简短摘要。
事件或方法 | 应用程序操作 |
---|---|
Launching 事件 | 执行非常少量的代码。不要执行资源密集型操作,例如,访问独立存储。 |
OnNavigatedFrom 方法 | 如果不是向后导航,则将 UI 状态保存到 State 字典。 |
Deactivated 事件 | 当应用程序被逻辑删除时,将应用程序状态保存到 State。同时,在应用程序终止时,将持续状态保存到独立存储。当应用程序进入休眠状态时,不要销毁内存中应用程序的状态。 |
Activated 事件 | 检查 IsApplicationInstancePreserved。若为 true,则不执行任何操作。若为 false,则使用 State 中的数据还原应用程序状态。 |
OnNavigatedTo 方法 | 检查页面是否为新实例。若不是,则状态自动保持。否则,如果 State 中存在数据,则使用该数据还原 UI。 |
Closing 事件 | 将持续应用程序数据保存到独立存储。 |
![]() |
---|
通过本节所述的事件,您可以在应用程序进入和离开前台时保存和还原状态。但是,推荐的做法是在状态数据发生更改时立即保存状态数据。例如,当收到来自网络的某个 Web 请求时,可以立即将其结果保存到磁盘和/或应用程序状态字典中。您不应等到 Deactivated 事件发生后才存储此数据。请记住,所有应用程序生命周期事件都强制限定应用程序在 10 秒钟的时间内完成所有任务。 |
补充:休眠(Dormant)
休眠是在7.1之后加进去的,也就是所谓的伪多任务。
当用户向前导航或导航出应用程序时,引发 Deactivated 事件后,操作系统将尝试使应用程序置于休眠状态。在此状态下,应用程序的所有线程均将停止,并且不进行任何处理操作,但应用程序仍完好地保留在内存中。如果从该状态中重新激活应用程序,应用程序无需重新创建任何状态,因为状态已保留。
如果在应用程序进入休眠状态后启动新的应用程序,这些应用程序需要更多的内存才能提供出色的用户体验,操作系统将开始逻辑删除休眠的应用程序以释放内存。
休眠和墓碑化的区别(个人理解,仅供参考):休眠是将所有应用程序信息保留在内存中,当用户恢复程序时,就不需要创建一个新的实例。而墓碑化的应用程序是穿件了一个新的实例,然后从PhoneApplicationService.State中加载原来的信息,使应用程序看上去和原来一样。
http://www.cnblogs.com/zhangdongzi/archive/2011/08/24/2152551.html
http://www.cnblogs.com/konck/archive/2012/01/14/2322245.html
http://msdn.microsoft.com/zh-cn/library/ff817008(v=VS.92).aspx
还有一个Idle detection问题,可以看这篇文章的后半部分:http://msdn.microsoft.com/zh-cn/windowsphone/gg546046.aspx