Windows Phone7 - 應用程序生命周期
在Windows Phone 上運行的應用程序從開始到程序運行結束,其整個生命周期都是由Windows Phone的執行模型所支配。執行模型被設計的目的就是為終端用戶實時提供快速的、反應靈敏的體驗。故,Windows Phone 7在設計的初衷是以單任務設計為主導,雖說在不久的將來微軟會步蘋果之后為自己的手機平臺添加多任務,但那是后話。
Windows Phone執行模型還維護著用戶使用應用程序和查看頁面所產生的日志。利用該日志就能定義電話后退鍵所遵循的后退路徑,從而提供給用戶一個能夠回退到不同應用程序和瀏覽頁面的后退選項。
當用戶通過導航鍵功能離開某一應用程序時,操作系統執行掛起該程序的步驟被稱之為tombstoning,中文名稱叫:“墓碑機制”。操作系統會維護 應用程序狀態信息。如果用戶返回到被掛起的應用程序程序中,此時操作系統會繼續執行被掛起應用程序的進程,并傳遞狀態數據給此應用程序。
一個應用程序會在用戶切換離開它時被邏輯刪除,然而除了這個一般規則仍然存有一些例外。操作系統可能需要額外的資源保證前臺運行程序的正常活動,那么 此時在操作系統運行的運應用程序有可能在任何時候被邏輯刪除,這點跟Android有點相似,唯一不同的是,Andriod 的KILL是殺死ACTIVITY頁面,而不是殺死應用程序,我記得沒錯的話,應該是這樣。
注意:在一般情況下調用應用程序并不會被邏輯刪除,但是當操作系統開啟一個應用時發現需要比當前可用資源更多的資源時,那么應用程序就可能被邏輯刪除。
由于Windows Phone 7是單任務手機操作系統,故與多任務為原型的Android 相比應用程序生命周期要簡單得多,Windows Phone 7的生命周期示意圖為如下:
根據上圖與Windows Phone 7生命周期相關的事件共分為以下五個部分:
- 啟動
- 運行
- 關閉
- 禁止
- 激活
而Android 的Activity 生命周期要來得復雜一些,具體看下圖:
根據上圖,Android 生命周期事件相關的共分為7大部分:
- 創建
- 重新啟動
- 活動可視時開始
- 活動與用戶交互之前
- 被掛起時
- 被停止時(有可能被銷毀)
- 被銷毀時
由于本篇是講述Windows Phone 7這里只和Android 的生命周期一個小小的比較,就不深入講Android內容,讀者有興趣的可以找一下相關的資料,下面繼續Windows Phone 7 的生命周期。
1.啟動
當用戶點擊了手機上應用程序安裝列表的某一應用程序,或者點擊了開始屏幕上的代表某一應用程序的小方塊圖標,此時應用程序就被啟動了。無論用戶以哪種 方式啟動應用程序,該程序的實例就會被創建。當應用程序被啟動了,也就是一個啟動事件被觸發了。處理這個啟動事件時,應用程序應該從一個獨立的存儲中讀取 所有必要的數據來為用戶創建一個新的應用程序會話進程。應用程序不應該試圖從以前的應用程序實例中恢復瞬時狀態。此是這是一個全新的應用實例。
Note that:啟動和激活事件是互斥的。
2.運行
當啟動事件被觸發了,一個應用程序就開始運行了。應用程序處于運行狀態時,用戶進行瀏覽該應用程序的頁面等相關操作,此時應用程序會自己管理自己的狀 態。如果應用程序處于運行狀態,那么與執行模型相關的唯一操作就是逐步的保存設置以及其他應用程序持久化數據,這樣做的目的是為了避免當應用程序的狀態發 生改變時需要保存大量的數據。
3.關閉
應用程序處于運行狀態之后的狀態是取決于用戶采用了哪種操作。一個可能的操作是用戶按下手機的回退鍵從而回退到應用程序的前一頁面,甚至翻過了應用程序的第一個頁面。當這種情況發生時,關閉事件會被觸發,從時應用程序被終止
了。處理關閉事件,應用程序應該把所有的持久化數據保存到獨立的存儲中。此時沒有必要保存瞬時狀態數據,即那些只有和前應用程序實例相關的數據。因為用戶如果要返回一個己經被終止的應用程序,唯一的方法應當是啟動它,打開它的首頁。這就是單任務的好處。
4.禁止
如果一個應用程序正在運行,隨后在操作系統前臺被另一個應用程序或者體驗替代,例如,鎖屏或者啟動一個Chooser,這時第一個應用程序將會被禁 止。禁止相當于Android的onPause事件。此時如果操作檢測到資源不足,可能會對該程序進行邏輯刪除。由于會存在被邏輯刪除的危險,所以并不能 保證一個被禁止的應用程序會被重新激活,所以在此事件的處理中應用程序需要一直把持久化數據保存到一個獨立的存儲空間。
Note that:禁止事件處理程序所進行的所有操作必須在10秒鐘內完成,否則操作系統將會直接終止應用程序而不是邏輯刪除。
5.激活
當一個應用程序被禁止后,有可能這個應用程序永遠不會被再次激活。用戶可能會從頭再重新啟動該應用程序,從而得到一個新的應用程序實例。或者用戶可以 啟動其他幾個應用程序,這樣就會把處于應用程序堆棧最后的即使利用回退鍵也不可能到達的欺騙性程序關閉掉。當然用戶也有繼續要使用原應用程序的可能性。這 種情況可能會發生在用戶不停地敲擊回退鍵來達到指定應用程序目的。這個和Android的回退鍵倒是十分相似。
開發人員可以使用墓碑機制事件來保存就應用程序狀態和頁面狀態。利用這些狀態,開發人員可以把應用程序恢復到最后一個正確的狀態。你要了解一下以下兩點:
- 應用程序狀態 是就應用程序的一種狀態且并不與任何特定頁面有關聯。應用程序狀態是在 PhoneApplicationService 類公開的事件中管理的。
- 頁面狀態 是一種應用程序頁面可見的狀態。它包含了諸如 ScrollViewer 控件中滾軸的位置和 TextBox 控件
中的內容等信息。頁面的狀態管理應該由OnNavigatedTo 和 OnNavigatedFrom 事件處理程序來處理。
下面我們就針對上述所講的,總結成一個DEMO吧:
首先我們在App.xaml文件中在針對的生命周期方法中鍵入代碼,以下代碼可供參考:
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"); }
以上代碼都做了注釋了。
下面運行模擬器,查看一下日志的輸出,ctrl+w+0:
當頁面啟動時:
導航進來時:
點擊back,導航出去時:
點擊下一頁并點擊BACK時:
注意:頁面先進入第二頁,并執行第二頁的onNavigatedTo,然后點擊BACK觸發第二頁的OnNavigatedFrom,之后再觸發第一頁的OnNavigatedOn。
在第一頁的時候點擊Start:
此時進入了應用程序生命周期的管理,執行失去激活事件。
最后,用戶停留在應用程序菜單列單上,單擊BACK按鈕:
如圖,應用程序執行了重新激活的事件,并執行了導航事件。
至此,生命周期課程學完了。覺得有一點跟ANDROID 差唱比較大的是,ANDROID是每個頁面的生命周期,而Window Phone
7的頁面是靠Navigated
,而整個應用程序的生命周期都歸app.xaml處理,這是兩者最大的不同吧。不知道將來WP7多任務會不會改變生命周期呢?呵呵。。
DEMO下載:Windows Phone 7生命周期