注:本文内容面向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