Windows Phone7 - 应用程序生命周期

openkk 13年前
     <p>在Windows Phone 上运行的应用程序从开始到程序运行结束,其整个生命周期都是由Windows Phone的执行模型所支配。执行模型被设计的目的就是为终端用户实时提供快速的、反应灵敏的体验。故,Windows Phone 7在设计的初衷是以单任务设计为主导,虽说在不久的将来微软会步苹果之后为自己的手机平台添加多任务,但那是后话。<br /> <br /> Windows Phone执行模型还维护着用户使用应用程序和查看页面所产生的日志。利用该日志就能定义电话后退键所遵循的后退路径,从而提供给用户一个能够回退到不同应用程序和浏览页面的后退选项。<br /> <br /> 当用户通过导航键功能离开某一应用程序时,操作系统执行挂起该程序的步骤被称之为tombstoning,中文名称叫:“墓碑机制”。操作系统会维护 应用程序状态信息。如果用户返回到被挂起的应用程序程序中,此时操作系统会继续执行被挂起应用程序的进程,并传递状态数据给此应用程序。<br /> <br /> 一个应用程序会在用户切换离开它时被逻辑删除,然而除了这个一般规则仍然存有一些例外。操作系统可能需要额外的资源保证前台运行程序的正常活动,那么 此时在操作系统运行的运应用程序有可能在任何时候被逻辑删除,这点跟Android有点相似,唯一不同的是,Andriod 的KILL是杀死ACTIVITY页面,而不是杀死应用程序,我记得没错的话,应该是这样。<br /> <br /> 注意:在一般情况下调用应用程序并不会被逻辑删除,但是当操作系统开启一个应用时发现需要比当前可用资源更多的资源时,那么应用程序就可能被逻辑删除。<br /> <br /> 由于Windows Phone 7是单任务手机操作系统,故与多任务为原型的Android 相比应用程序生命周期要简单得多,Windows Phone 7的生命周期示意图为如下:<br /> <br /> <img alt="Windows Phone7 - 应用程序生命周期" src="https://simg.open-open.com/show/943623d93699c56cde3cb73743ffc62d.png" width="768" height="868" /><br /> 根据上图与Windows Phone 7生命周期相关的事件共分为以下五个部分:</p>    <ul>     <li>启动<br /> </li>     <li>运行<br /> </li>     <li>关闭<br /> </li>     <li>禁止<br /> </li>     <li>激活<br /> </li>    </ul>    <p>而Android 的Activity 生命周期要来得复杂一些,具体看下图:<br /> <br /> <img alt="Windows Phone7 - 应用程序生命周期" src="https://simg.open-open.com/show/bc84b4fd41d775db5de86e71cac697a8.png" width="545" height="711" /><br /> <br /> 根据上图,Android 生命周期事件相关的共分为7大部分:</p>    <ul>     <li>创建<br /> </li>     <li>重新启动<br /> </li>     <li>活动可视时开始<br /> </li>     <li>活动与用户交互之前<br /> </li>     <li>被挂起时<br /> </li>     <li>被停止时(有可能被销毁)<br /> </li>     <li>被销毁时<br /> </li>    </ul>    <p>由于本篇是讲述Windows Phone 7这里只和Android 的生命周期一个小小的比较,就不深入讲Android内容,读者有兴趣的可以找一下相关的资料,下面继续Windows Phone 7 的生命周期。</p>    <h2>1.启动</h2>    <p>当用户点击了手机上应用程序安装列表的某一应用程序,或者点击了开始屏幕上的代表某一应用程序的小方块图标,此时应用程序就被启动了。无论用户以哪种 方式启动应用程序,该程序的实例就会被创建。当应用程序被启动了,也就是一个启动事件被触发了。处理这个启动事件时,应用程序应该从一个独立的存储中读取 所有必要的数据来为用户创建一个新的应用程序会话进程。应用程序不应该试图从以前的应用程序实例中恢复瞬时状态。此是这是一个全新的应用实例。<br /> Note that:启动和激活事件是互斥的。</p>    <h2>2.运行</h2>    <p>当启动事件被触发了,一个应用程序就开始运行了。应用程序处于运行状态时,用户进行浏览该应用程序的页面等相关操作,此时应用程序会自己管理自己的状 态。如果应用程序处于运行状态,那么与执行模型相关的唯一操作就是逐步的保存设置以及其他应用程序持久化数据,这样做的目的是为了避免当应用程序的状态发 生改变时需要保存大量的数据。</p>    <h2>3.关闭</h2>    <p>应用程序处于运行状态之后的状态是取决于用户采用了哪种操作。一个可能的操作是用户按下手机的回退键从而回退到应用程序的前一页面,甚至翻过了应用程序的第一个页面。当这种情况发生时,关闭事件会被触发,从时应用程序被终止<br /> 了。处理关闭事件,应用程序应该把所有的持久化数据保存到独立的存储中。此时没有必要保存瞬时状态数据,即那些只有和前应用程序实例相关的数据。因为用户如果要返回一个己经被终止的应用程序,唯一的方法应当是启动它,打开它的首页。这就是单任务的好处。</p>    <h2>4.禁止</h2>    <p>如果一个应用程序正在运行,随后在操作系统前台被另一个应用程序或者体验替代,例如,锁屏或者启动一个Chooser,这时第一个应用程序将会被禁 止。禁止相当于Android的onPause事件。此时如果操作检测到资源不足,可能会对该程序进行逻辑删除。由于会存在被逻辑删除的危险,所以并不能 保证一个被禁止的应用程序会被重新激活,所以在此事件的处理中应用程序需要一直把持久化数据保存到一个独立的存储空间。<br /> <br /> Note that:禁止事件处理程序所进行的所有操作必须在10秒钟内完成,否则操作系统将会直接终止应用程序而不是逻辑删除。</p>    <h2>5.激活</h2>    <p>当一个应用程序被禁止后,有可能这个应用程序永远不会被再次激活。用户可能会从头再重新启动该应用程序,从而得到一个新的应用程序实例。或者用户可以 启动其他几个应用程序,这样就会把处于应用程序堆栈最后的即使利用回退键也不可能到达的欺骗性程序关闭掉。当然用户也有继续要使用原应用程序的可能性。这 种情况可能会发生在用户不停地敲击回退键来达到指定应用程序目的。这个和Android的回退键倒是十分相似。 <br /> <br /> 开发人员可以使用墓碑机制事件来保存就应用程序状态和页面状态。利用这些状态,开发人员可以把应用程序恢复到最后一个正确的状态。你要了解一下以下两点:</p>    <ul>     <li>应用程序状态 是就应用程序的一种状态且并不与任何特定页面有关联。应用程序状态是在 PhoneApplicationService 类公开的事件中管理的。<br />  </li>     <li>页面状态 是一种应用程序页面可见的状态。它包含了诸如 ScrollViewer 控件中滚轴的位置和 TextBox 控件<br /> 中的内容等信息。页面的状态管理应该由OnNavigatedTo 和 OnNavigatedFrom 事件处理程序来处理。<br /> </li>    </ul>    <p>下面我们就针对上述所讲的,总结成一个DEMO吧:<br /> <br /> 首先我们在App.xaml文件中在针对的生命周期方法中键入代码,以下代码可供参考:<br /> <br /> </p>    <pre class="brush:c#; toolbar: true; auto-links: false;">private void Application_Launching(object sender, LaunchingEventArgs e) { //Trace the event for debug purposes Utils.Trace("Application Launching");  //Create new data object variable TravelReportInfo travelReportInfo = null;  //尝试从以前保存过的独立数据加载数据 using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication()) { //验证是否存在 if (isf.FileExists("TravelReportInfo.dat")) { using (IsolatedStorageFileStream fs = isf.OpenFile("TravelReportInfo.dat", System.IO.FileMode.Open)) { //Read the file contents and try to deserialize it back to data object XmlSerializer ser = new XmlSerializer(typeof(TravelReportInfo)); object obj = ser.Deserialize(fs);  //如果成功反序列化,则初始化变量 if (null != obj && obj is TravelReportInfo) travelReportInfo = obj as TravelReportInfo; else travelReportInfo = new TravelReportInfo(); } } else //If previous data not found, create new instance travelReportInfo = new TravelReportInfo(); }  //设置当前的数据上下文为tranvelInfo,页面启动完毕后我们就可以通过dataContext 获取数据 RootFrame.DataContext = travelReportInfo; }  private void Application_Activated(object sender, ActivatedEventArgs e) { //Trace the event for debug purposes Utils.Trace("Application Activated");  //Create new data object variable TravelReportInfo travelReportInfo = null;  //试着找出以前的数据状态 if (PhoneApplicationService.Current.State.ContainsKey("UnsavedTravelReportInfo")) { //如果找到,则从中还原出来,并删除掉之前保存的状态 travelReportInfo = PhoneApplicationService.Current.State["UnsavedTravelReportInfo"] as TravelReportInfo;  PhoneApplicationService.Current.State.Remove("UnsavedTravelReportInfo"); }  //因为应用可能会被逻辑删除,所以不能保证会被激活 ,如果程序被逻辑删除则创建新的数据 if (null != travelReportInfo) RootFrame.DataContext = travelReportInfo; else RootFrame.DataContext = new TravelReportInfo(); }    Application_Deactivated      private void Application_Deactivated(object sender, DeactivatedEventArgs e) { //Trace the event for debug purposes Utils.Trace("Application Deactivated");  //将当前的应用程序状态保存进数据中 PhoneApplicationService.Current.State.Add("UnsavedTravelReportInfo", RootFrame.DataContext as TravelReportInfo); }         private void Application_Closing(object sender, ClosingEventArgs e) { //Trace the event for debug purposes Utils.Trace("Application Closing"); }</pre>    <p></p>    <p><br /> 以上代码都做了注释了。 <br /> <br /> 下面运行模拟器,查看一下日志的输出,ctrl+w+0: <br /> <br /> 当页面启动时: <br /> <br /> <img alt="Windows Phone7 - 应用程序生命周期" src="https://simg.open-open.com/show/c674f630eea0e987d454f03c6205de73.png" width="729" height="453" /> <br /> <br /> 导航进来时: <br /> <br /> <img alt="Windows Phone7 - 应用程序生命周期" src="https://simg.open-open.com/show/8660ed0122b2aa9df2ce43d1e02dd84f.png" width="695" height="642" /> <br /> <br /> 点击back,导航出去时: <br /> <br /> <img alt="Windows Phone7 - 应用程序生命周期" src="https://simg.open-open.com/show/ab372bc27bbebc4bdcab0c1006f73111.png" width="643" height="615" /> <br /> <br /> 点击下一页并点击BACK时: <br /> <br /> <img alt="Windows Phone7 - 应用程序生命周期" src="https://simg.open-open.com/show/680fc72f2cbb75273c72e7eae66e4d70.png" width="372" height="56" /> <br /> <br /> 注意:页面先进入第二页,并执行第二页的onNavigatedTo,然后点击BACK触发第二页的OnNavigatedFrom,之后再触发第一页的OnNavigatedOn。 <br /> <br /> 在第一页的时候点击Start: <br /> <br /> <img alt="Windows Phone7 - 应用程序生命周期" src="https://simg.open-open.com/show/fb0513cf8e3d49af74c61f1c5475a645.png" width="372" height="29" /> <br /> <br /> 此时进入了应用程序生命周期的管理,执行失去激活事件。 <br /> <br /> 最后,用户停留在应用程序菜单列单上,单击BACK按钮: <br /> <br /> <img alt="Windows Phone7 - 应用程序生命周期" src="https://simg.open-open.com/show/494540f572dc103a65cd5bd5a564d1f5.png" width="403" height="58" /> <br /> <br /> 如图,应用程序执行了重新激活的事件,并执行了导航事件。 <br /> <br /> 至此,生命周期课程学完了。觉得有一点跟ANDROID 差唱比较大的是,ANDROID是每个页面的生命周期,而Window Phone<br /> 7的页面是靠Navigated<br /> ,而整个应用程序的生命周期都归app.xaml处理,这是两者最大的不同吧。不知道将来WP7多任务会不会改变生命周期呢?呵呵。。 <br /> <br /> DEMO下载:<a href="/misc/goto?guid=4959500042304723715" rel="nofollow">Windows Phone 7生命周期</a> </p>