[WP8.1UI控件编程]Windows Phone大数据量网络图片列表的异步加载和内存优化

简介:


11.2.4 大数据量网络图片列表的异步加载和内存优化

    虚拟化技术可以让Windows Phone上的大数据量列表不必担心会一次性加载所有的数据,保证了UI的流程性。对于虚拟化的技术,我们不仅仅只是依赖其来给列表加载数据,还可以利用虚拟化的特性去做更多的事情。虚拟化技术有一个很重要的特性就是,它可以准确地判断出哪些列表项处于手机屏幕中,可以动态地去更新这些数据。基于这样的特性,我们可以给列表的功能做更多的优化。

    那么下面我们基于一个例子来讲解利用虚拟化技术去做列表的性能优化。有这么一个需求,需要实现一个图片的列表,图片都是来自网络的,然后数据集合也很大。做这个网络图片列表功能时会面临着两个问题,一个是图片的加载会比较耗时,两外一个是当不断地滑动会让数据集合加载的图片占用的内存会越来越高。

    对于第一个问题,可以采用异步加载的方式来解决,这样列表加载完之后,图片再显示出来,列表首次加载的速度会很快。那么我们可以通过后台线程调用网络请求下载图片,下载完图片之后再触发UI线程把图片显示出来。

    第二个问题是要解决内存的问题,那么可以使用弱引用类型(WeakReference类)来存储图片的数据。弱引用就是不保证不被垃圾回收器回收的对象,它拥有比较短暂的生命周期,在垃圾回收器扫描它所管辖的内存区域过程中,一旦发现了只具有弱引用的对象,就会回收它的内存,不过一般情况下,垃圾回收器的线程优先级很低,也就不会很快发现那些只有弱引用的对象。当内存的使用会影响到程序的流畅运行的时候,垃圾回收器,就会按照优先次序把存在时间长的弱引用对象回收,从而释放内存。所以弱引用特别适合在当前这种情况下,占用大量内存,但通过垃圾回收功能回收以后很容易重新创建的图片对象。图片下载完之后会存放在弱引用对象里面,当检查到数据被回收的时候,再进行异步加载,当然你也可以把图片用独立存储存起来,这样也就免去了再次请求网络的操作。

    下面我们来实现网络图片列表的异步加载和内存优化的示例:

代码清单11-8网络图片列表(源代码:第11章\Examples_11_8)

    (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对象的数据集合。

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



本文转自linzheng 51CTO博客,原文链接:http://blog.51cto.com/linzheng/1559361


相关实践学习
基于MaxCompute的热门话题分析
Apsara Clouder大数据专项技能认证配套课程:基于MaxCompute的热门话题分析
相关文章
|
7月前
|
机器学习/深度学习 大数据 关系型数据库
基于python大数据的青少年网络使用情况分析及预测系统
本研究基于Python大数据技术,构建青少年网络行为分析系统,旨在破解现有防沉迷模式下用户画像模糊、预警滞后等难题。通过整合多平台亿级数据,运用机器学习实现精准行为预测与实时干预,推动数字治理向“数据驱动”转型,为家庭、学校及政府提供科学决策支持,助力青少年健康上网。
|
8月前
|
分布式计算 安全 大数据
别等被黑客敲门才醒悟:大数据如何帮你防住网络攻击?
别等被黑客敲门才醒悟:大数据如何帮你防住网络攻击?
371 32
|
监控 数据可视化 大数据
Axure设计的“广东省网络信息化大数据平台”数据可视化大屏
本文介绍由Axure设计的“广东省网络信息化大数据平台”数据可视化大屏。大屏分为左中右三区域,共九个模块,涵盖设备占比、数据异常、地市排名、关键指标、地图分布、订单信息等。通过环形图、柱状图、饼图等多种图表形式,将复杂数据直观呈现,助力决策者全面掌握数据动态,推动广东省网络信息化建设发展。
997 135
|
大数据
“你朋友圈的真面目,大数据都知道!”——用社交网络分析看透人情世故
“你朋友圈的真面目,大数据都知道!”——用社交网络分析看透人情世故
530 16
|
移动开发 前端开发 Java
Java最新图形化界面开发技术——JavaFx教程(含UI控件用法介绍、属性绑定、事件监听、FXML)
JavaFX是Java的下一代图形用户界面工具包。JavaFX是一组图形和媒体API,我们可以用它们来创建和部署富客户端应用程序。 JavaFX允许开发人员快速构建丰富的跨平台应用程序,允许开发人员在单个编程接口中组合图形,动画和UI控件。本文详细介绍了JavaFx的常见用法,相信读完本教程你一定有所收获!
14947 5
Java最新图形化界面开发技术——JavaFx教程(含UI控件用法介绍、属性绑定、事件监听、FXML)
|
前端开发 Linux C#
一款开源、免费、美观的 Avalonia UI 原生控件库 - Semi Avalonia
一款开源、免费、美观的 Avalonia UI 原生控件库 - Semi Avalonia
1685 10
|
人工智能 API Apache
推荐3款开源、美观且免费的WinForm UI控件库
推荐3款开源、美观且免费的WinForm UI控件库
3408 6
|
网络协议 API Windows
MASM32编程调用 API函数RtlIpv6AddressToString,windows 10 容易,Windows 7 折腾
MASM32编程调用 API函数RtlIpv6AddressToString,windows 10 容易,Windows 7 折腾
|
API C# 开发者
基于Material Design风格开源、免费的WinForms UI控件库
基于Material Design风格开源、免费的WinForms UI控件库!
518 0
|
Linux C# Android开发
分享3款开源、免费的Avalonia UI控件库
分享3款开源、免费的Avalonia UI控件库
2002 0