Windows Phone 7 Tip - 小心使用 OnNavigatedTo 事件
在开发一个多页面的Windows Phone 7应用程序的过程中,偶然发现与页面导航(Page Navigation)有关的一些潜在“秘密”。
在我的应用中,页面A 的程序响应某按钮的点击事件,通过NavigationService.Navigate() 方法跳转到另一个页面B。而在B 页面中的OnNavigatedTo 事件中,根据业务逻辑的需要,会进行一些判断,然后在一些业务数据不满足条件的情况下,会弹出消息对话框(采用MessageBox.Show()方法)。这一操作流程似乎没有什么问题。但经过细心的测试发现,在该消息对话框弹出后,如果用户不做任何操作,大约10秒钟后整个应用程序会被强行关闭。
而这一现象居然在联机Debug时无法再现,只有通过应用程序列表直接运行起来才会发生!
经过反复试验和推测,我认为“强行关闭应用”这一步操作应该是由操作系统来处理的。再想想看,也相当合乎逻辑。我们可以尝试在B 页面的OnNavigatedTo 事件函数入口处设置一个断点,然后在联机Debug 环境下触发页面跳转。你会看到,在该事件被触发的那一刻,页面A 仍显示在手机屏幕中,表明页面导航尚未结束,正处于进行过程中。而在此时弹出MessageBox 对话框,恰恰阻碍了页面跳转的顺利进行,使其处于“卡死”状态(MessageBox.Show()方法会令程序流停止于该语句调用的地方,并在用户对消息对话框进行响应后继续)。而根据Windows Phone 7 的相关Development Guide,页面处于停滞状态达10秒者,杀无论。这就解释了为什么在上述例子中,当用户在10秒内不作出任何响应,应用程序就会被强行关闭了。
从这个角度出发,我们也不难猜想,如果在OnNavigatedTo 事件中试图执行一些“重量级”操作,导致进程停滞达10秒以上时,同样也会被系统强行关闭。
用图示来描述本文内容:
如果一定要在刚刚跳转到B 页面时就执行必要的处理逻辑,并弹出MessageBox 的话,可以考虑使用B 页面的Loaded 事件。该事件的触发时间稍晚于OnNavigatedTo 事件,但此时整个页面导航已经执行完毕,A 页面已完全退出手机屏幕。因此,在Loaded 事件里弹出MessageBox 是比较安全的。但值得注意的是,Loaded 事件仅在进入该页面时触发一次,而OnNavigatedTo 事件则在每次显示该页面时都会被触发(例如:在显示B 页面的状态下按Start 按钮或Search 按钮,然后再按下Back 键回到B 页面时)。
有兴趣的朋友可以下载示例代码来实测一下:
下载代码:http://up.2cto.com/2011/1111/20111111023019486.rar
希望本文能够给开发Windows Phone 7 多页面应用程序的朋友起到提醒的作用。
作者: 李靖南Email: elecpiano@gmail.com
新浪微博: http://weibo.com/zengnami
MSN: zengnami@hotmail.com
QQ: 52717278
关于作者:
从事微软平台解决方案的设计与实现。主要专注方于Silverlight 及Windows Phone 7 应用开发,及前者与微软云计算平台(Azure)的结合。