虚拟化技术可让Windows Phone上的大数据量列表没必要担忧会一次性加载全部的数据,保证了UI的流程性。对于虚拟化的技术,咱们不单单只是依赖其来给列表加载数据,还能够利用虚拟化的特性去作更多的事情。虚拟化技术有一个很重要的特性就是,它能够准确地判断出哪些列表项处于手机屏幕中,能够动态地去更新这些数据。基于这样的特性,咱们能够给列表的功能作更多的优化。html
那么下面咱们基于一个例子来说解利用虚拟化技术去作列表的性能优化。有这么一个需求,须要实现一个图片的列表,图片都是来自网络的,而后数据集合也很大。作这个网络图片列表功能时会面临着两个问题,一个是图片的加载会比较耗时,两外一个是当不断地滑动会让数据集合加载的图片占用的内存会愈来愈高。编程
对于第一个问题,能够采用异步加载的方式来解决,这样列表加载完以后,图片再显示出来,列表首次加载的速度会很快。那么咱们能够经过后台线程调用网络请求下载图片,下载完图片以后再触发UI线程把图片显示出来。缓存
第二个问题是要解决内存的问题,那么可使用弱引用类型(WeakReference类)来存储图片的数据。弱引用就是不保证不被垃圾回收器回收的对象,它拥有比较短暂的生命周期,在垃圾回收器扫描它所管辖的内存区域过程当中,一旦发现了只具备弱引用的对象,就会回收它的内存,不过通常状况下,垃圾回收器的线程优先级很低,也就不会很快发现那些只有弱引用的对象。当内存的使用会影响到程序的流畅运行的时候,垃圾回收器,就会按照优先次序把存在时间长的弱引用对象回收,从而释放内存。因此弱引用特别适合在当前这种状况下,占用大量内存,但经过垃圾回收功能回收之后很容易从新建立的图片对象。图片下载完以后会存放在弱引用对象里面,当检查到数据被回收的时候,再进行异步加载,固然你也能够把图片用独立存储存起来,这样也就免去了再次请求网络的操做。性能优化
下面咱们来实现网络图片列表的异步加载和内存优化的示例:网络
代码清单11-8:网络图片列表(源代码:第11章\Examples_11_8)dom
(1)建立数据实体类Data类,在Data类里面封装异步加载图片和弱引用的逻辑。异步
Data.cs文件主要代码 ------------------------------------------------------------------------------------------------------------------ // Data类从INotifyPropertyChanged派生,要实现绑定属性改变的事件,用于图片异步请求完成以后能够更新到UI上 public class Data: INotifyPropertyChanged { // 图片名字属性 public string Name { get; set; } // 当前的页面对象,用于触发UI线程 public Page Page { get; set; } // 图片的网络地址 private Uri imageUri; public Uri ImageUri { get { return imageUri; } set { if (imageUri == value) { return; } imageUri = value; bitmapImage = null; } } // 若引用对象,用于存储下载好的图片对象 WeakReference bitmapImage; // ImageSource属性用于绑定到列表的Image控件上 public ImageSource ImageSource { get { if (bitmapImage != null) { // 若是弱引用没有没回收,则取弱引用的值 if (bitmapImage.IsAlive) return (ImageSource)bitmapImage.Target; else Debug.WriteLine("数据已经被回收"); } // 弱引用已经被回收那么则经过图片网络地址进行异步下载 if (imageUri != null) { Task.Factory.StartNew(() =>{ DownloadImage(imageUri);}); } return null; } } // 下载图片的方法 void DownloadImage(object state) { HttpWebRequest request = WebRequest.CreateHttp(state as Uri); request.BeginGetResponse(DownloadImageComplete, request); } // 完成图片下载的回调方法 async void DownloadImageComplete(IAsyncResult result) { HttpWebRequest request = result.AsyncState as HttpWebRequest; HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(result); // 读取网络的数据 Stream stream = response.GetResponseStream(); int length = int.Parse(response.Headers["Content-Length"]); // 注意须要把数据流从新复制一份,不然会出现跨线程错误 // 网络下载到的图片数据流,属于后台线程的对象,不能在UI上使用 Stream streamForUI = new MemoryStream(length); byte[] buffer = new byte[length]; int read=0; do { read = stream.Read(buffer, 0, length); streamForUI.Write(buffer, 0, read); } while (read == length); streamForUI.Seek(0, SeekOrigin.Begin); // 触发UI线程处理位图和UI更新 await Page.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { BitmapImage bm = new BitmapImage(); bm.SetSource(streamForUI.AsRandomAccessStream()); // 把图片位图对象存放到若引用对象里面 if (bitmapImage == null) bitmapImage = new WeakReference(bm); else bitmapImage.Target = bm; //触发UI绑定属性的改变 OnPropertyChanged("ImageSource"); } ); } // 属性改变事件 async void OnPropertyChanged(string property) { var hander = PropertyChanged; if (hander != null) await Page.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { hander(this, new PropertyChangedEventArgs(property)); }); } public event PropertyChangedEventHandler PropertyChanged; }
(2)使用ListView控件绑定到数据Data对象的数据集合。async
MainPage.xaml文件主要代码 ------------------------------------------------------------------------------------------------------------------ <ListView x:Name="listView"> <ListView.ItemTemplate> <DataTemplate> <StackPanel> <TextBlock Text="{Binding Name}" Height="80"></TextBlock> <Image Source="{Binding ImageSource}" Width="200" Height="200"></Image> </StackPanel> </DataTemplate> </ListView.ItemTemplate> </ListView>
MainPage.xaml.cs文件主要代码 ------------------------------------------------------------------------------------------------------------------ public MainPage() { InitializeComponent(); // 建立一个有1000个Data对象的数据集合 List<Data> Items = new List<Data>(); for (int i = 0; i < 1000; i++) { // 在网络地址后面加上index=i是为了保证每一个网络地址的不同 // 这样就不会产生网络数据缓存,更加接近真实的网络图片列表 Items.Add(new Data { Name = "Test" + i, Page = this, ImageUri = new Uri("http://pic002.cnblogs.com/images/2012/152755/2012120917494440.png?index=" + i) }); } listView.ItemsSource=Items; }
本文来源于《深刻理解Windows Phone 8.1 UI控件编程》性能
源代码下载:http://vdisk.weibo.com/s/zt_pyrfNHoezI大数据
欢迎关注个人微博@WP林政
WP8.1技术交流群:372552293