注:本文內容面向Runtime App。
在新建項目后,細心觀察,你會發現在App類中有以下代碼:
// TODO: 將此值更改為適合您的應用程序的緩存大小 rootFrame.CacheSize = 1;
這行代碼放在了OnLaunched方法中,CacheSize是Frame類的一個公共屬性。
我們知道,Frame類負責完成頁面之間的導航,它本身就是一個容器控件。CacheSize屬性用於告訴Frame對象,要緩存的頁面數量。近日,有人提問說,這個緩存頁面數是不是導航記錄的數量?
明確地告訴你:非也。
Frame的導航記錄在BackStack屬性中,這個Cache並不是用來緩存頁面的導航記錄的,一定要注意啊,不要搞混了。
CacheSize屬性是用於設置要保留頁面實例的個數。當Frame導航到某個頁面時,通常情況下,是要調用頁面的構造函數來創建某頁的新實例的。即,不論你是向前導航還是向后導航,只要導航到某頁,某頁都會重新實例化。因此,就可以理解為什么Frame類用於導航的Navigate方法要這樣定義了:
public bool Navigate(System.Type sourcePageType)
這與Silverlight中的導航不同,SL中是傳遞URI的,而這里是傳遞頁面類的Type,就因為得到某個頁面類的Type,才會在導航是new一個實例出來。
感覺很抽象嗎?沒事,示例是無敵學習利器,還猶豫什么,動手。
1、啟動VS,新建一個”空白應用程序(Windows Phone)“項目。據說MS會統一所有平台的命名,當然這是需要的,也是蓋茨的夢想。不管叫什么,系統還是一樣的,只是叫法不同罷了。
2、在App類中,找到OnLaunch方法,把CaheSize改為0。
rootFrame.CacheSize = 0;
3、把項目默認生成的MainPage.xaml刪掉,因為它的存在,嚴重影響示例的演示,為什么? 待會兒再告訴你。
4、向項目中添加三個空白頁,這個會了吧? 不會的話,就按Ctrl + Shift + A,試試。
5、三個頁面的結構差不多,所以這里我只說第一個頁面。XAML代碼如下:
<Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition/> </Grid.RowDefinitions> <TextBlock Grid.Row="0" Text="頁面一" Style="{StaticResource HeaderTextBlockStyle}"/> <StackPanel Grid.Row="1"> <TextBlock Text="頁面初始化" FontSize="45" Margin="3,10,2,5"> <TextBlock.Foreground> <SolidColorBrush x:Name="slb" Color="White"/> </TextBlock.Foreground> </TextBlock> <Button Content="下一頁" Grid.Row="1" Click="OnNext"/> </StackPanel> </Grid> <Page.Resources> <Storyboard x:Key="std" RepeatBehavior="5x"> <ColorAnimation Duration="0:0:0.5" Storyboard.TargetName="slb" Storyboard.TargetProperty="Color" From="Purple" To="Yellow"/> </Storyboard> </Page.Resources>
在Page的資源列表中,聲明了一個Storyboard,用動畫來改變顯示”頁面初始化“的TextBlock的文本顏色。
思路是這樣的:在頁面類的構造函數中播放該動畫,並且動畫是重復播放5次的(由RepeatBehavior指定)。如果頁面發生了實例化操作,那么構造函數也被調用,動畫就會被播放。在頁面之間導航時,通過觀看頁面上的顏色改變動畫是否會播放就可以知道構造函數是否被調用,從而了解到頁面是否產生了新實例。
6、在頁面類的構造函數中,取出資源中的Storyboard對象,然后開始播放動畫。
public Page1 () { this.InitializeComponent(); NavigationCacheMode = Windows.UI.Xaml.Navigation.NavigationCacheMode.Required; // 如果構造函數被調用,就播放動畫 Storyboard std = this.Resources["std"] as Storyboard; std.Begin(); }
在上面代碼中還有這么一句:
NavigationCacheMode = Windows.UI.Xaml.Navigation.NavigationCacheMode.Required;
Page類有個NavigationCacheMode屬性,必須將它設置為Enabled或者Required,不要設置為Disabled。因為Disabled表示禁用頁面緩存,如果禁用,就算CacheSize設置為100萬也沒用,頁面實例都不會緩存。
那么,Enabled和Required值又有啥區別呢? 區別在於是否強制緩存。如果設置為Enabled並且沒有超出CacheSize指定的頁面緩存的數目,那么頁面實例會被緩存;但是,一旦緩存的頁面數量超過了CacheSize指定的數量,哪怕你將頁面的緩存模式設置為Enabled,頁面實例也不再進行緩存。
而Required則不同,就算已緩存的頁面實例的總數已經超過CacheSize的值,設置了Required模式的頁面仍然會強制緩存。
不過,要注意一點:無論何時,都不要把CacheSize設置為0,如果為0,就算頁面使用了Required模式,都不會發生緩存。
也就是說,應該始終讓CacheSize的值大於0。
本例有三個頁面,就把CacheSize設置為3吧。
rootFrame.CacheSize = 3;
使用頁面緩存,可以在應用程序運行過程中,讓頁面的類實例暫時保存,不需要在每次導航到頁面的時候都進行實例化操作,節省性能開銷,尤其是當某些頁面在初始化時會比較耗時間的時候更有用,只在第一次訪問時實例化,后面再次訪問時就不再實例化,這樣可以提高程序的響應速度。
不管頁面實例是否被緩存,當導航進入頁面后,OnNavigatedTo方法都會被調用。但是,如果切換到其他應用或者回到開始屏幕而使應用程序掛起(中斷運行)后,再次回到應用程序,頁面不會發生重新實例化,OnNavigatedTo方法也不會被調用。
應用程序在掛起后會引發App的Suspending事件,當再次回到應用后,會引發App的Resuming事件。
注意這與WP以前的Silverlight框架的應用程序不同,SL頁面在離開或回到應用程序,都會觸發導航事件,而從RT庫移植過來的API與Win 8x應用取得統一,離開或回到當前應用程序不會引發頁面的導航事件。
關於本文中提到的示例,下載地址為:http://files.cnblogs.com/tcjiaan/%E9%A1%B5%E9%9D%A2%E7%BC%93%E5%AD%98%E7%A4%BA%E4%BE%8B.rar