理解Windows Phone 7應用程序執行模型,墓碑機制,啓動器和選擇器及更多內容——Part 3

作者: Yochay Kiriaty

在前兩篇文章(part 1part 2 )中你已經學習了應用程序生命週期中的不同事件——Launching, Deactivated, Closing和Activated以及它們之間的區別。在這些知識和這個代碼 的基礎上,我們繼續向前探索。

保存臨時數據和導航到正確的頁面

回憶一下,我們程序的第二頁包含兩個文本框,一個用來允許用戶輸入一個將被保存到聯繫人信息中的電話號碼,另一個讓用戶可以輸入一條待發送的短信息。當我們在墓碑狀態的程序中使用啓動器(Launchers)和選擇器(Choosers)時這將會變得十分有用。

在開始前首先要明確一下問題。最簡單的方式是做一個小實驗:

  1. 在Visual Studio中,打開你的程序。
  2. 導航至第二個頁面並在兩個文本框中輸入一些信息。
  3. 這將會使你的程序被停用(關於此請參見這個系列的第二部分 )。
  4. 按一次返回鍵以回到你的應用程序。這會導致你的模擬器顯示黑屏。
  5. 按下F5,或者用任何方法重啓你的Visual Studio調試會話以重新激活你的程序。(再強調 一次,如果你錯過了某些內容,請看這個系列的第二部分)
  6. 現在,你的程序應該處於運行狀態並能看到程序的第二頁。然而,文本框中的內容卻是空的。在停用程序之前你所輸入的內容已經不在了。它們消失了!

clip_image002

從這個小實驗中你可以得知你在程序中輸入的數據在程序停用(記住,你的程序被終止了)時不會自動被保存。在重新激活時就意味着重新開始了程序的一個新實例。這表明所有控件在默認情況下是沒有數據的,除非你爲它們加載數據。

有關墓碑程序最重要的用戶可以不返回到你的應用程序 ,因此你的程序可能不會被重新激活 。如果你希望它發生,那麼你需要將要恢復的任何數據保存到磁盤。當然作爲一個開發人員這完全取決於你自己和你的工作職責去保存和獲取應用程序的數據。

我們來區分一下這兩種要保存的數據的類型(摘自MSDN ):

  • 持久數據 ——被多個程序的所有實例共享的數據。持久數據的保存和載入都在獨立存儲區 。在不同應用程序執行時各個程序的設置就是持久化數據的一個例子。
  • 臨時數據 ——描述一個應用程序單個實例狀態的數據。臨時數據存儲在PhoneApplicationService 類的State 字典中。一個墓碑程序在重新被激活時會恢復它的臨時狀態。

在下篇文章中我們會講解持久數據如何與獨立存儲區一同工作。現在讓我們重點關注一下如何管理臨時數據和使用State字典。

在SDK中的一個新類就是PhoneApplicationService 。它提供了對應用程序生命週期中的各種狀態的訪問。這包含程序閒置行爲的管理和程序狀態的管理。這個類在墓碑這個遊戲中扮演了主角,因爲它對外公開了Launching, Deactivate, Activated和Closing事件,它們在App.xaml.cs文件中有對應的方法(你已經見過了)。這個類還包括一個只讀的類型爲IDictionary 的State屬性。這個字典的重要性在於當你的程序被墓碑化處理後它會被Windows Phone操作系統持久化在你的應用程序中。當應用程序被重新激活,存在字典中的對象會被返回。如果你只是想讓應用程序從墓碑狀態返回那麼你不用將這些臨時對象保存到磁盤上。因此,如果你想使用State字典,要確保只在其中保存臨時數據——那些你不介意丟失或只對當前應用程序實例有用的數據。在我們的例子中,我們保存電話號碼和短信息的內容。

請注意你保存到這個字典中的對象必須是可序列化的 (serializable),否則你會在停用事件觸發時得到一個關於操作系統無法禁用或恢復使用你的對象的異常。

MSDN中的最佳實踐 建議你在 OnNavigatedFrom 事件中將臨時的頁面數據保存在State字典中,並且在OnNavigatedTo 事件中載入數據。

我更新了程序從而可以保存電話號碼和短消息到這個字典中,並在每次導航到頁面時載入它。如果一個“完整的”新的程序實例(意思是Launching事件被觸發)啓動時,State字典是空的。

注意以下的變化,頁面2的信息在頁面之間導航切換時被保存。也就是你在頁面2按下返回鍵,應用程序返回到頁面1的時候。如果你在頁面1點擊“導航到下一頁”按鈕,你的程序會導航到頁面2。OnNavigateTo事件(在頁面2中)會被觸發,同時上面的代碼會使控件加載數據。這非常重要因爲如果你仔細觀察Visual Studio輸出窗口的信息將會發現每次你導航到頁面2時,它的構造函數都會執行。這說明每次在頁面2中按下返回鍵時,該頁會被銷燬,因此你每次從頁面1導航到頁面2時,頁面2都重新被創建。如果想觀察這個行爲,可以在兩個頁面中不斷的切換,同時注意每次從頁面1導航到頁面2時頁面2的構造函數都會被調用。如果在程序中將OnNavigatedFrom方法中的內容註釋掉,那麼在頁面間切換時,你會看到第二頁的信息沒有被保存。

clip_image004

現在將程序變爲墓碑你會看到電話號碼和短信息已被保存,不只是在頁面切換時,還在離開程序後返回時發生。導航到頁面2,輸入一個電話號碼和一些文本信息,按下Windows鍵使程序變爲墓碑。你應該可以能看到Deactivated事件的跟蹤信息然後程序被終止掉。再按下返回鍵同時不要忘記在Visual Studio中按F5重啓調試會話。你的程序將會返回到墓碑狀態同時你會看到Activated事件被觸發,然後是頁面2的構造函數。接着你會看到OnNavigatedTo的信息,如果一切順利,你會看到"Found phone number"和"Found Sms Msg"兩行信息,正如下圖顯示的那樣。

clip_image006

現在一切都很好,我還希望解釋一下墓碑化Windows Phone應用程序的工作方式。不過現在,是時候開始我們的遊戲了,同時在實戰中展示一些很酷的內容。

首先, 我添加了一個助手類Logger用來記錄所有的跟蹤信息並把它們顯示在主頁面(頁面1)的文本框中。Logger的目的向你證明你的應用程序最終被終止掉同時State字典的的確確是在工作。這個日誌類還可以讓你在模擬器的非調試模式下運行應用程序,同時可以獲取跟蹤信息並顯示在日誌文本框中。

Logger類

Logger類實現了一個非常簡單的單例模式 (不過可能不是線程安全的)。這個類設計成單例主要是當你的應用程序結束時只有一個類的實例從內存中被移除,除此之外還有相關的事件和在不同事件中加載的數據。這個類有一個string成員log,還有一個DataTime成員用來保存Logger對象的創建時間。通過Logger類你可以向日志添加一些新行還可以獲取整個日誌。這非常有利於調試,這也正是Logger的職責所在。每次你使用Util類添加一個跟蹤時,你都可以將它加入到Logger中。

通常單例的實現沒有公共的構造函數。然而如果你要將這個類保存到State子典中,這意味着Logger類必須是可序列化的,因此必須有一個公共的默認(空的)構造函數。否則你在停用或激活程序時會得到一個異常。

爲了“查看”日誌,我在MainPage.xaml.cs中加入了OnNavigatedTo並將日誌中的文本信息加載到主頁面的logTextBox 控件。因此每次你導航到程序的主頁面中都會看到日誌文件被打印出來。這可以使你看到程序的跟蹤信息而不需要在VS中調試程序(感謝的Jaime Rodriguez 的建議)。現在來試試。

  1. 首先需要部署你的程序到模擬器。你可以在Visual Studio的解決方案資源管理器面板中右擊你的項目,或者從生成菜單中點擊“部署”。
  2. 在模擬器中,點擊電話右上角白色的箭頭導航到應用程序列表。
  3. 你應該會看到一個非常短的應用程序列表。從列表中找到你的程序。如果你使用了本篇文章中的代碼,則應用程序的名字是LWP.AppLifeCycle。
  4. 應用程序啓動後,你會在主頁面文本框中看到跟蹤信息。你可能想改變電話的設置(通過點擊扳手按鈕)來調整模擬器的縮放等級到100%。日誌文本框中的文本很小從而可以顯示儘可能多的歷史記錄而無需滾動條。
  5. 在日誌文本框中你會看到應用程序創建和主頁面構造函數的跟蹤信息。
  6. 點擊Next按鈕。
  7. 在第二頁中,輸入一個電話號碼或一些信息。
  8. 然後點擊Windows鍵停用你的程序。在模擬器中,你應該會看到起始界面。
  9. 點擊返回鍵回到你的應用程序。這會重新激活你的應用程序並恢復程序到最後一個瀏覽過的頁面,也就是第二頁,如果一切順利,你會看到在步驟7中輸入過的信息。
  10. 在第二頁中,點擊返回鍵回到第一頁。在日誌文本框中看到的跟蹤信息應與下圖一致:

clip_image008

跟蹤信息中最有意思的一段是在虛線中的,下面的代碼片段來自應用程序的Activatedd事件。

在這段代碼中,你會看到我們在State字典中檢索Logger對象。找個對象在Deactivated事件觸發時被放到了State字典中。假設Logger對象被找到,我們創建一個臨時的叫logger的對象(注意這不是我們在當前程序中真正使用的logger對象)。然後對比從字典中獲取的logger對象和剛剛激活的應用程序中的logger對象的創建時間。正如你看到的,存在一個時間差。我們在停用程序時保存到State字典中的logger比新logger的時間長。在代碼中你可以看出我們不能真正的初始化舊的logger;它的創建時間和日誌都被恢復並打印到文本框中。所以虛線中的每一行信息都取決於應用程序上一次運行時停用事件的觸發情況。

虛線後的第一行顯示了第二頁的構造函數,不出所料,這表明“新的”應用程序被激活並從我們停用的應用程序中返回到第二頁。

總結

現在你已經在實踐中見過了全部的4個事件:Launching, Deactivated, Activated和Closing。我希望你能清楚程序在何時沒有運行,在何時終止以及如果你的數據沒有保存它在何時會丟失。並且在你返回程序時,無論觸發的是Activated事件或是Launching事件,你都會得到一個程序的新實例(我們的單例小實驗已經證實了這一點)。

State字典可以在Deactivated和Activated事件中保存臨時數據,而且在我們要討論選擇器和啓動器的下篇文章中它被證實是一個非常有用的工具。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章