一、WP第三方應用程式限制
WP一次僅允許一個第三方應用程式在前台運行,這就意味著使用者在操作手機的時候只能開啟一個第三方應用,讓人覺得WP是一個單任務作業系統。
但是和普遍理解的單任務作業系統不同,WP提供了一種機制,這就是Tombstone(墓碑),它能夠讓使用者在不同的第三方應用之間切換時保留使用者曾經的操作狀態(這是多任務作業系統最擅長做的事情),提升使用者體驗。
二、Tombstone
Tombstone直譯過來就是“墓碑”,還可以直觀理解為休眠、掛起、暫停或者凍結等等,在WP中它表示程式終止的一個標記,但是不能理解為徹底終結進程並退出應用程式。
Tombstone能夠為Windows Phone提供以單任務的能力完成多任務的功能。如何才能實現以單任務的能力完成多任務的功能?
答案就是WP提供的Tombstone執行模型。
三、WP生命週期
在講Tombstone執行模型前先熟悉下WP的生命週期。
Tombstone是WP生命週期裡一個重要的狀態,它是以事件為執行模型的。所謂一圖勝千言,我們通過兩張圖片對比下WP7和WP7.5生命週期管理的異同:
1、WP7應用程式生命週期過程
2、WP7.5應用程式生命週期過程
在下面的圖中,圓圈表示應用程式的狀態,矩形顯示應用程式應管理其狀態的應用程式層級或頁面層級的事件。
註:圖片均來源於參考部落格。
四、Tombstone執行模型
1、執行過程
Tombstone是以事件為執行模型的。在WP7中,一共有4個基本的處理事件:Launching(啟動)、Closing(關閉)、Activated和Deactivated。每一次應用程式的啟用,最少會觸發其中的一個事件。程式是否Tombstone,完全依據程式當前進入的事件,這些事件由項目下的入口檔案App.xaml.cs進行管理和描述。
建立一個WP項目,開啟項目下的App.xaml.cs,可以看到如下4個基本事件的處理函數:
Events // Code to execute when the application is launching (eg, from Start) // This code will not execute when the application is reactivated private void Application_Launching(object sender, LaunchingEventArgs e) { } // Code to execute when the application is activated (brought to foreground) // This code will not execute when the application is first launched private void Application_Activated(object sender, ActivatedEventArgs e) { } // Code to execute when the application is deactivated (sent to background) // This code will not execute when the application is closing private void Application_Deactivated(object sender, DeactivatedEventArgs e) { } // Code to execute when the application is closing (eg, user hit Back) // This code will not execute when the application is deactivated private void Application_Closing(object sender, ClosingEventArgs e) { }
其中,Application_Deactivated就是事件發生Tombstone時執行的行為,Application_Activated就是為Tombstone恢複狀態時發生的事件行為。
我們可以針對這四個事件,為Tombstone的產生(Deactivated事件)和解除(Activated事件)編程做些處理,比如當產生Tombstone時進行臨時資料的儲存等,而解除Tombstone時將臨時資料取出,對於使用者而言,一存一取正好保證了使用者體驗的一致性。
2、處理事件
(1)、Launching事件
Launching(進入)事件是每一個第三方應用在第一次運行時都必須執行的事件,它主要負責應用程式的初始化。這個事件與Closing事件是對應的,一個運行正常的應用程式執行了Launching事件,最後必然也要執行Closing事件。
Launching事件必須是第一次啟動執行的,對於處於Tombstone解除狀態的應用程式不會執行該事件。
這個事件的特點:當程式第一次啟動時會調用,當程式重新啟用時不調用。
(2)、Activated事件
Activated(啟用)事件是Tombstone的核心。判斷一個應用程式是否進入Tombstone,只需觀察Activated事件是否已經在執行。這個事件適合讀取一些臨時資料的操作。
每一個啟用的應用程式都是使用者在手機前台應用中能夠直觀感受到的,此時你可以認為這個前台應用已經啟用。
這個事件的特點:當程式重新啟用的時候調用,當程式啟動時不調用。
(3)、Deactivated事件 (應用進入Tombstone的事件)
Deactivated(失去啟用)事件與Activated事件一起組成了完整的Tombstone。也就是說當應用程式執行Deactivated事件,該應用會處於Tombstone(休眠狀態),能夠再次喚醒應用的只有Activated事件。
但是必須注意,Deactivated(失去啟用)事件是孤立的,並不和哪個事件一一對應,也就是說程式處於Deactivated,可以再觸發Launching、Closing和Activated事件中的任何一個。
下面是幾種常見的WP執行Deactivated事件的情境:
a、使用者單擊Start按鈕回到主畫面或者啟動另一個應用程式;
b、手機螢幕被鎖定;
c、電話呼入或者收到新簡訊;
d、推送服務或者其他訊息提醒;
e、電池電量低強制彈出警告。
這個事件的特點:當程式失去啟用的時候調用,當程式關閉的時候不調用。
(4)、Closing事件
Closing(關閉)事件是與Launching事件對應的,雖然一個應用程式未必會執行該事件(比如死機、手機沒電或其他未捕獲異常中斷等)。
這個事件的特點:當程式關閉時調用該事件,當程式失去啟用時則不調用。
大家可以參考下面的代碼,分別跟蹤在啟動時、單擊模擬器Start按鈕以及Back按鈕時VS的Output視窗的輸出,加深對這四個事件的理解:
Events /// <summary> ///當程式第一次啟動時會調用 當程式重新啟用時不調用 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Application_Launching(object sender, LaunchingEventArgs e) { Debug.WriteLine("{0}進入Launching事件", DateTime.Now.ToLongTimeString()); } /// <summary> /// 當程式重新啟用的時候調用 當程式啟動時不調用 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Application_Activated(object sender, ActivatedEventArgs e) { Debug.WriteLine("{0}進入Activated事件", DateTime.Now.ToLongTimeString()); if (PhoneApplicationService.Current.State.ContainsKey(phoneApplicationServicedata)) { string content = PhoneApplicationService.Current.State[phoneApplicationServicedata] as string; Debug.WriteLine("{0}", content); } } /// <summary> /// 當程式失去啟用的時候調用 當程式關閉的時候不調用 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Application_Deactivated(object sender, DeactivatedEventArgs e) { Debug.WriteLine("{0}進入Deactivated事件", DateTime.Now.ToLongTimeString()); string content = "Hello Windows Phone!"; if (content != null) { PhoneApplicationService.Current.State[phoneApplicationServicedata] = "臨時資料:" + content; } } /// <summary> /// 當程式關閉時調用 當程式失去啟用時不調用 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Application_Closing(object sender, ClosingEventArgs e) { Debug.WriteLine("{0}進入Closing事件", DateTime.Now.ToLongTimeString()); }
參考:
http://msdn.microsoft.com/zh-cn/library/ff817008(v=VS.92).aspx
http://www.cnblogs.com/linzheng/archive/2011/02/14/1954764.html