ListView在Android应用里扮演非常重要的角色,但很多开发者在使用ListView时都遇到过不少麻烦。一个常见的问题是:列表中要显示一系列记录,每条记录带有一张缩略图(产品照片、用户头像等等),而这个缩略图是通过一个远程URL地址来标识的。这样的应用场景该如何实现呢?
为了将复杂的逻辑分离,我们单独写一个名为RemoteImageHelper的类来处理“异步下载图片并更新到界面”这个问题,这个类能够实现以下功能:
图片开始下载前,ImageView里显示一个表示“正在加载”的占位图;
图片在后台下载,下载完成后显示在ImageView里;
若图片下载失败,ImageView显示一个表示下载失败的占位图;
下面让我们来看一下实现代码:
首先需要有一个方法下载远程图片,这里我们不用把图片下载到手机上,直接返回一个InputStream类型的结果即可。如果运行时这个方法报错,请检查是否在AndroidManifest.xml里添加了android.permission.INTERNET权限。
然后是最主要的异步加载图片方法,“正在下载”和“下载失败”的图片可根据需要自己替换。代码如下所示:
关于缓存:在这个例子里我们使用一个内存中的HashMap作为图片缓存,它实现简单但当应用退出后缓存就会被清除。在实际项目里,你可以考虑实现一个基于文件的缓存机制,即将下载的图片保存到SD卡上,注意要定期清除长期不用的图片以节约存储空间。
如何使用这个类呢?下面是一个例子。请注意,为了达到更好的演示效果,代码里在调用loadImage()方法时第三个参数用false禁止了图片缓存功能,在实际项目中,你很可能需要改为true来避免重复下载图片以便提高性能。
以上代码中的MyRecord是一个简单的POJO类,表示一个业务对象,它具有id、label和imageUrl三个属性。你可以在完整的工程代码中找到它。
<a href="http://developer.android.com/reference/android/os/Handler.html">Handler</a>
<a href="http://lichen.blog.51cto.com/697816/486402">android的消息处理机制</a>
<a href="http://stackoverflow.com/questions/541966/how-do-i-do-a-lazy-load-of-images-in-listview">How do I do a lazy load of images in ListView</a>
<a href="http://code.google.com/p/android/issues/detail?id=13959">Issue 13959:Make listviews more programmer friendly</a>