Windows 8 Metro開發疑難雜症(三)——導航(2),數據保存,數據虛擬化


我在這個系列的第一篇就講到了導航的問題,不過可能有些問題還沒講明白,所以這里再寫一篇關於導航的博客。

這里有兩個問題:

1.為什么在調用Frame.Navigate方法的時候不能直接傳簡單類型以外的對象?

2.為什么頁面每次back的時候都會初始化頁面?

我先來講下VS的項目模版,在我們建立項目的時候如果選的不是空白項目,VS自動會創建一個包含Common文件夾的項目,而每個頁面都繼承自LayoutAwarePage,LayoutAwarePage幫我們做了很多必要的處理,看里面的代碼你會發現LayoutAwarePage重寫了NavigateTo和NavigateFrom方法,而多了兩個LoadState和SaveState兩個虛方法。這樣我們幾乎可以忘了NavigateTo和NavigateFrom方法了,直接用LoadState和SaveState方法就行了。這里還得說下為什么LayoutAwarePage重寫了兩個方法,看LayoutAwarePage的代碼我們可以發現,LayoutAwarePage在NavigateTo方法里面做了數據恢復的處理,當處理完了會調用LoadState方法,並把原來保存的數據傳給LoadState方法,這里的數據只有當back的時候才會有,因為只有在back的時候才會需要恢復數據。LayoutAwarePage在NavigateFrom方法里面做了數據保存的處理,當從當前頁導航到其他頁面的時候就會保存你的數據,具體保存什么數據是需要你自己處理的。

然后我們再看下項目模版是如何幫我們恢復好保存數據的.

我們所有經過SaveState方法保存的數據都是SuspensionManager這個類來處理的,當程序啟動的時候,會在APP類的OnLaunched方法里面會調用 SuspensionManager.RegisterFrame初始化SuspensionManager,如果程序是從掛起狀態恢復的那么還會調用SuspensionManager.RestoreAsync方法來恢復數據。而當程序處於掛起狀態的時候,會在APP類的OnSuspending方法里面調用SuspensionManager.SaveAsync來保存數據(數據的保存是以文件形式保存的)。

到這數據的恢復和保存已經講完了,然后我要將下前面提到的第一個問題,為什么在調用Frame.Navigate方法的時候不能直接傳簡單類型以外的對象?

問題就出在SuspensionManager.SaveAsync方法里面,因為這個方法會調用Frame.GetNavigationState方法,這時候如果你頁面傳遞的參數是復雜對象,那么直接crash,因為Frame.GetNavigationState無法序列化你的對象,就算你已經為你的類加上[DataContract]和[DataMenber]標記也沒用,對於這個問題我也問了微軟的相關技術人員,給我的答復是在傳遞對象的時候把對象先序列化成字符串,然后再在使用的時候反序列化成對象,這不是坑爹的嗎!!!

 

下面講上面提及的第二個問題,為什么頁面每次back的時候都會初始化頁面?

對於這個問題我是這么認為的(純屬個人觀點,有臆測成分,歡迎拍磚)。

我覺得之所以每次back的時候頁面都會初始化,很大程度上是從內存的使用率來考慮的。我們從商店下載的APP,很大部分的APP都是以圖片來展示內容的,由於平板的屏幕肯定比手機大,那同時顯示的圖片數量勢必會比較多,就算你啟用了虛擬化技術還是會有這個問題的,一張圖片的體積差不多能頂得上一部小說了,而一個頁面同時顯示較多的圖片勢必會占用較多的內存,而一個APP會有很多的頁面,如果每一個頁面都這樣的話那么一個APP所占用的內存將會有多大!現在當從當前頁導航到其他頁面的時候我認為系統會把原來頁面釋放掉以節約內存開銷,這樣你的APP配合數據虛擬化技術在內存的開銷上始終會處於一個穩定的狀態(我們目前開發的APP內存基本維持在60-80MB之間)。

另外我要說下什么是數據虛擬化技術,數據的虛擬化是列表類控件的專有的。假如你有1000條數據作為數據源給列表控件,如果你沒有啟用數據虛擬化(默認是開啟的),那么列表控件將會加載1000個item,每一個item都會占用內存資源,可想而知你的app要占用掉多少的資源,其實不只是內存的開銷,還有就是在你綁定數據源的時候出現卡的現象(因為列表控件要一下子初始化1000個item,不卡才怪!)。幸好目前的gridview,listview,listbox,flipview都默認啟用數據虛擬化的,這樣你有1000條數據的情況下,系統只要初始化10條或者更少的item(具體初始化多少條系統計算的),這樣一個減少了內存開銷,還一個是加快了列表控件的初始化速度。

數據的虛擬化其實是依靠列表控件的容器(ItemsPanel)來實現的,這些列表控件默認的容器都是從VirtualizingPanel繼承過來的,在win8種WrapGrid和VirtualizingStackPanel都是支持數據虛擬化的容器。我們自己也是可以自定義支持虛擬化的容器的,不過這個過程是很復雜的。

目前我用了一款社交類的APP,我可以確定這個APP沒用啟用虛擬化技術,它有分頁功能,當我一直往下加載頁面的時候內存蹭蹭的往上漲,當我大概瀏覽到100頁的時候內存占用已經有1G了,你沒看錯,是1G。

 

本篇到此!預告下下一篇

Window 8開發疑難雜症(四)——數據庫

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM