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

时间:2021-08-27 02:22:10

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=;
do
{
read = stream.Read(buffer, , length);
streamForUI.Write(buffer, , read);
} while (read == length);
streamForUI.Seek(, 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 = ; i < ; 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;
}

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

本文来源于《深入理解Windows Phone 8.1 UI控件编程》

源代码下载:http://vdisk.weibo.com/s/zt_pyrfNHoezI

欢迎关注我的微博@WP林政

WP8.1技术交流群:372552293

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

  1. &lbrack;WP8&period;1UI控件编程&rsqb;Windows Phone VirtualizingStackPanel、ItemsStackPanel和ItemsWrapGrid虚拟化排列布局控件

    11.2.2 VirtualizingStackPanel.ItemsStackPanel和ItemsWrapGrid虚拟化排列布局控件 VirtualizingStackPanel.ItemsSta ...

  2. &lbrack;WP8&period;1UI控件编程&rsqb;Windows Phone动画方案的选择

    8.1 动画方案的选择 Windows Phone的动画实现方式有线性插值动画(3种类型).关键祯动画(4种类型)和基于帧动画,甚至还有定时器动画,然后动画所改变的UI元素属性可以是普通的UI元素属性 ...

  3. &lbrack;WP8&period;1UI控件编程&rsqb;Windows Phone理解和运用ItemTemplate、ContentTemplate和DataTemplate

    2.2.5 ItemTemplate.ContentTemplate和DataTemplate 在理解ItemTemplate.ContentTemplate和DataTemplate的关系的之前,我 ...

  4. &lbrack;WP8&period;1UI控件编程&rsqb;Windows Phone XAML页面的编译

    1.1.2 XAML页面的编译 Windows Phone的应用程序项目会通过Visual Studio完成XAML页面的编译,在程序运行时会通过直接链接操作加载和解析XAML,将XAML和过程式代码 ...

  5. &lbrack;WP8&period;1UI控件编程&rsqb;Windows Phone自定义布局规则

    3.2 自定义布局规则 上一节介绍了Windows Phone的系统布局面板和布局系统的相关原理,那么系统的布局面板并不一定会满足所有的你想要实现的布局规律,如果有一些特殊的布局规律,系统的布局面板是 ...

  6. &lbrack;WP8&period;1UI控件编程&rsqb;SemanticZoom控件实现分组列表

    11.1.5 SemanticZoom实现分组列表 SemanticZoom控件可以让用户实现一种更加高级的列表,这种列表可以对列表的项目进行分组,同时这个SemanticZoom控件会提供两个具有相 ...

  7. 《深入理解Windows Phone 8&period;1 UI控件编程》基于最新的Runtime框架

    <深入理解Windows Phone 8.1 UI控件编程>本书基于最新的Windows Phone 8.1 Runtime SDK编写,全面深入地论述了最酷的UI编程技术:实现复杂炫酷的 ...

  8. 大数据量时 Mysql LIMIT如何正确对其进行优化(转载)

    以下的文章主要是对Mysql LIMIT简单介绍,我们大家都知道LIMIT子句一般是用来限制SELECT语句返回的实际行数.LIMIT取1个或是2个数字参数,如果给定的是2个参数,第一个指定要返回的第 ...

  9. zList一个块状链表算法可以申请和释放同种对象指针,对于大数据量比直接new少需要差不多一半内存

    zList是一个C++的块状内存链表,特点: 1.对于某种类别需要申请大量指针,zList是一个很好的帮手,它能比new少很多内存. 2.它对内存进行整体管理,可以将数据和文件快速互操作 3.和vec ...

随机推荐

  1. java(2014)实现对mysql数据库分页的代码

    package util; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultS ...

  2. POJ 2568&sol;ZOJ 1965 Decode the Tree

    题意:在树中,每次删去节点值最小的叶子结点. 每删去一个点,就给出与这相连的点的值,直到最后只剩下一个根结点,给这N-1个数,重新建立这个树. 思路: 给出的节点号按次序存入到数组a中,将未给出的数存 ...

  3. 1033&period; Labyrinth&lpar;dfs&rpar;

    1033 简单dfs 有一点小小的坑 就是图可能不连通 所以要从左上和右下都搜一下 加起来 从讨论里看到的 讨论里看到一句好无奈的回复 “可不可以用中文呀...” #include <iostr ...

  4. xml语法规则

    所有 XML 元素都须有关闭标签 在 HTML,经常会看到没有关闭标签的元素: <p>This is a paragraph <p>This is another paragr ...

  5. discuz 更换域名 导致qq登录不能用的问题

    今天论坛换了域名,导致qq登录不能用.于是各种百度,终于找到了解决方案,特此记录一下 解决方法:1,首先清空你站点的id和key,并且设置为未注册云平台: 2,找一个新域名(未开过云平台的就可),如果 ...

  6. &lbrack;Java Web学习&rsqb;JSP中uri&equals;&quot&semi;http&colon;&sol;&sol;java&period;sun&period;com&sol;jsp&sol;jstl&sol;core&quot&semi;报红错误

    在官网下载jstl.jar和standard.jar,问题解决.

  7. 参考RPC

    普遍RPC在客户端需要提供接口,如果不提供则无法进行调用.同时,因为客户端也依赖提供的接口,服务端的升级.优化所带来的更新,客户端也要及时的更新API,否则会带来影响.这样,就带来了依赖接口,常常更新 ...

  8. Datagrip导入导出为一个sql文件详细说明 &lpar;mysql&rpar;

    Datagrip导入导出为一个sql文件详细说明 导出: (我的无法截图, 借用一张) 导入: (我的无法截图, 再借用一张) 完

  9. VS Code 工具配置和格式化

    { "onSave": true, "javascript": { "indent_size": 2, "indent_char& ...

  10. interface21 - web - ContextLoaderListener(Spring Web Application Context加载流程)

    前言 最近打算花点时间好好看看spring的源码,然而现在Spring的源码经过迭代的版本太多了,比较庞大,看起来比较累,所以准备从最初的版本(interface21)开始入手,仅用于学习,理解其设计 ...