Windows Phone 7 确实有多任务
是的,这是我说的。这么说因为这是真的。一个Windows Phone绝对是一个多任务的设备。我可以在听音乐的同时玩游戏,或者在上网的时候收邮件。错误的消息是我们应用程序的开发人员传出的,在开发我们发现不能构建在后台运行的程序。
在我为Windows Phone 7工作的几个月中,我只能提出2个真正有说服力的在我的电话中运行后台应用程序的原因。
- 播放音乐的程序。如Pandora程序。我完全认同它在后台中运行。如果音乐停止了用户一定会发现的。
- 需要从设备传感器中获取数据的程序,如GPS,如果程序没有运行,我就无法告诉你已经走完了你想走的4英里路程。
在这两种情况之外,我并没有觉得有哪些情况是必须要让程序能在后台运行的。(如果你的程序在上述任何一类中,你可以向“当权者”呼吁要访问一个能使程序在后台运行的“超级API”。但我还是要提醒你……为获取访问权准备一个非常充分的理由。)
你可能会问“但是我如何从我的Web Service中获得更新呢?难道我不用运行就能获取吗?”我的答案是NO,你不能这么做。有一个叫做推送通知服务的强大机制可以以一种优雅的方式解决这个问题,这个我会在第19日中讲解。
对于剩下的程序,有一个叫做“墓碑”的机制允许我们让程序看起来总是在运行,即使进程已经被结束。下图演示了它是如何工作的:
正如你在上图中看到的,当用户进入或退出程序时我们可以利用停用和重新激活事件。通过这些事件,我们可以让用户觉得程序从来没有停止过运行。当我们加入独立存储(第15日)和推送通知(第19日)时,这将会变为一个非常给力的故事。
模拟多任务
在你的App.xaml.cs文件中有四个内建的方法。来看一下带有内置注释的默认状态。
03 |
private void Application_Launching( object sender, LaunchingEventArgs e) |
08 |
private void Application_Activated( object sender, ActivatedEventArgs e) |
13 |
private void Application_Deactivated( object sender, DeactivatedEventArgs e) |
18 |
private void Application_Closing( object sender, ClosingEventArgs e) |
“Launching” 和“Closing”方法在通常情况下使用:通过通常方法启动和退出应用程序(例如用返回键退出,或者从程序列表中启动)。Activated和 Deactivated方法用于非常规方式的进入和退出。例如,使用返回键回到我们的应用程序。或者由于接电话而离开程序。这些都是非常规的。我建议大量 测试这些情况,但有一些规则可以遵循。
你应该在用户退出程序时使用这些方法来保存状态信息,并且在他们返回时更新这些状态,这样就产生了他们从未退出的错觉。这么做的原因很简单:
- 大多数用户都不会意识到在他们离开程序后,程序仍然在后台消耗着系统资源和电池电量(如果你正在阅读本文,就你不属于大多数用户了)。
- 大多数应用程序都没有在后台运行的必要。这是节省系统资源的好方法。
在程序被停用时保存你的状态
在用户退出时要做的第一件事就是保存它们的信息。在我的例子中,我构建了一个看似一直在运行的计时器,即使当它没有运行时。如果你想看全部代码,翻到文章底部,见“下载代码示例”一节。我只在这里展示和墓碑相关的部分代码,但文章底部的代码是完整可用的应用程序。
为了保存数据,我使用PhoneApplicationService类。我会在明天(第15日)讲独立存储,一种更持久的保存数据的方法。在我的例子中,我想知道你何时退出了程序,所以我要计算你退出时和下次运行程序时两者之间的差值。
1 |
private void Application_Deactivated( object sender, DeactivatedEventArgs e) |
3 |
PhoneApplicationService.Current.State[ "LeftTime" ] = DateTime.Now; |
在我的应用程序中,当载入页面时还有一个OnNavigatedTo事件。如果“LiftTime”的值存在,我就使用它,否则我假设你是第一次启动程序。
在程序被重新激活时恢复你的状态
在这个例子中,我恢复了在退出时保存下来的值。
01 |
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e) |
03 |
base .OnNavigatedTo(e); |
04 |
if (PhoneApplicationService.Current.State.ContainsKey( "LeftTime" )) |
06 |
DateTime deactivated = (DateTime)PhoneApplicationService.Current.State[ "LeftTime" ]; |
07 |
secondsSinceStart = ( int )(DateTime.Now - deactivated).TotalSeconds + ( int )PhoneApplicationService.Current.State[ "ElapsedTime" ]; |
12 |
else secondsSinceStart = 0; |
通过这种方法,我能保持一个连续的计时器,甚至是当我们离开程序时。如果你去问任何用户,他们都会告诉你程序一直在运行。他们唯一能看到的现象是在程序加载较慢时出现的“Resuming”屏幕。实际上我不得不强制程序暂停才捕获到下面的截图:
以上是墓碑机制背后的基础知识。在退出时保存状态,并在回去时恢复。你的用户绝不会知道这其中的差别,同时你还可以为他们提供更好的续航时间,性能和用户体验