[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


相关实践学习
简单用户画像分析
本场景主要介绍基于海量日志数据进行简单用户画像分析为背景,如何通过使用DataWorks完成数据采集 、加工数据、配置数据质量监控和数据可视化展现等任务。
SaaS 模式云数据仓库必修课
本课程由阿里云开发者社区和阿里云大数据团队共同出品,是SaaS模式云原生数据仓库领导者MaxCompute核心课程。本课程由阿里云资深产品和技术专家们从概念到方法,从场景到实践,体系化的将阿里巴巴飞天大数据平台10多年的经过验证的方法与实践深入浅出的讲给开发者们。帮助大数据开发者快速了解并掌握SaaS模式的云原生的数据仓库,助力开发者学习了解先进的技术栈,并能在实际业务中敏捷的进行大数据分析,赋能企业业务。 通过本课程可以了解SaaS模式云原生数据仓库领导者MaxCompute核心功能及典型适用场景,可应用MaxCompute实现数仓搭建,快速进行大数据分析。适合大数据工程师、大数据分析师 大量数据需要处理、存储和管理,需要搭建数据仓库?学它! 没有足够人员和经验来运维大数据平台,不想自建IDC买机器,需要免运维的大数据平台?会SQL就等于会大数据?学它! 想知道大数据用得对不对,想用更少的钱得到持续演进的数仓能力?获得极致弹性的计算资源和更好的性能,以及持续保护数据安全的生产环境?学它! 想要获得灵活的分析能力,快速洞察数据规律特征?想要兼得数据湖的灵活性与数据仓库的成长性?学它! 出品人:阿里云大数据产品及研发团队专家 产品 MaxCompute 官网 https://www.aliyun.com/product/odps&nbsp;
相关文章
|
1月前
|
C# 开发者 Windows
基于Material Design风格开源、易用、强大的WPF UI控件库
基于Material Design风格开源、易用、强大的WPF UI控件库
|
2月前
|
运维 监控 网络协议
JAVA 线上故障排查完整套路,从 CPU、磁盘、内存、网络、GC
JAVA 线上故障排查完整套路,从 CPU、磁盘、内存、网络、GC
74 0
|
2月前
|
算法 API C++
【Qt UI】QT 窗口/控件置顶方法详解
【Qt UI】QT 窗口/控件置顶方法详解
75 0
|
2月前
|
算法 前端开发 C++
【Qt UI相关】Qt设置窗体或控件的背景色透明
【Qt UI相关】Qt设置窗体或控件的背景色透明
30 0
|
2月前
|
存储 Linux 编译器
Linux C/C++ 编程 内存管理之道:探寻编程世界中的思维乐趣
Linux C/C++ 编程 内存管理之道:探寻编程世界中的思维乐趣
52 0
|
2月前
|
前端开发 搜索推荐 开发者
SAP UI5 sap.m.Column 控件的 minScreenWidth 属性介绍
SAP UI5 sap.m.Column 控件的 minScreenWidth 属性介绍
32 0
|
20天前
|
机器学习/深度学习 缓存 监控
linux查看CPU、内存、网络、磁盘IO命令
`Linux`系统中,使用`top`命令查看CPU状态,要查看CPU详细信息,可利用`cat /proc/cpuinfo`相关命令。`free`命令用于查看内存使用情况。网络相关命令包括`ifconfig`(查看网卡状态)、`ifdown/ifup`(禁用/启用网卡)、`netstat`(列出网络连接,如`-tuln`组合)以及`nslookup`、`ping`、`telnet`、`traceroute`等。磁盘IO方面,`iostat`(如`-k -p ALL`)显示磁盘IO统计,`iotop`(如`-o -d 1`)则用于查看磁盘IO瓶颈。
|
1月前
|
缓存 安全 Java
Java并发编程进阶:深入理解Java内存模型
【4月更文挑战第6天】Java内存模型(JMM)是多线程编程的关键,定义了线程间共享变量读写的规则,确保数据一致性和可见性。主要包括原子性、可见性和有序性三大特性。Happens-Before原则规定操作顺序,内存屏障和锁则保障这些原则的实施。理解JMM和相关机制对于编写线程安全、高性能的Java并发程序至关重要。
|
11天前
|
安全 网络安全 Android开发
云端防御策略:融合云服务与网络安全的未来构建高效的Android应用:从内存优化到电池寿命
【4月更文挑战第30天】 随着企业加速向云计算环境转移,数据和服务的云端托管成为常态。本文探讨了在动态且复杂的云服务场景下,如何构建和实施有效的网络安全措施来保障信息资产的安全。我们将分析云计算中存在的安全挑战,并展示通过多层次、多维度的安全框架来提升整体防护能力的方法。重点关注包括数据加密、身份认证、访问控制以及威胁检测与响应等关键技术的实践应用,旨在为读者提供一种结合最新技术进展的网络安全策略视角。 【4月更文挑战第30天】 在竞争激烈的移动市场中,Android应用的性能和资源管理已成为区分优秀与平庸的关键因素。本文深入探讨了提升Android应用效率的多个方面,包括内存优化策略、电池
|
13天前
|
网络虚拟化 数据安全/隐私保护 数据中心
【专栏】对比了思科与华为网络设备的基本配置、接口、VLAN、路由、访问控制列表及其它关键命令
【4月更文挑战第28天】本文对比了思科与华为网络设备的基本配置、接口、VLAN、路由、访问控制列表及其它关键命令。尽管两者在很多操作上相似,如设备命名(思科:`hostname`,华为:`sysname`)、查看版本信息(思科:`show version`,华为:`display version`),但在某些方面存在差异,如接口速率设置(两者都使用`speed`和`duplex`,但命令结构略有不同)和VLAN配置(华为的`port hybrid`命令)。