ListView 是一种可以显示一系列项目并能进行滚动显示的 View,每一行的Item可能包含复杂的结构,可能会从网络上获取icon等的一些图标信息,就现在的网络速度要想保持ListView运行的很好滚动流畅是做不到的
所以这里就需要把这些信息利用多线程实现异步加载
实现这样功能的类:
public class AsyncImageLoader { private HashMap<String, SoftReference<Drawable>> imageCache; public AsyncImageLoader() { this.imageCache = new HashMap<String, SoftReference<Drawable>>(); } // 下载图片 public static Drawable loadImageFromUrl(String url) { InputStream localInputStream = null; try { localInputStream = (InputStream) new URL(url).getContent(); Drawable localDrawable = null; if (localInputStream != null) localDrawable = Drawable.createFromStream(localInputStream, "src"); return localDrawable; } catch (Exception localException) { localException.printStackTrace(); return null; } } public HashMap<String, SoftReference<Drawable>> getImageCache() { return imageCache; } public void setImageCache( HashMap<String, SoftReference<Drawable>> imageCache) { this.imageCache = imageCache; } @SuppressWarnings("unchecked") public Drawable loadDrawable(String imageURL, ImageCallback paramImageCallback) { boolean bool = this.imageCache.containsKey(imageURL); Drawable localDrawable = null; if (bool) { localDrawable = (Drawable) ((SoftReference) (imageCache) .get(imageURL)).get(); return localDrawable; } else { ImageHandler imageHandler = new ImageHandler(this, paramImageCallback, imageURL); new ImageThread(this, imageURL, imageHandler).start(); } return localDrawable; } public abstract interface ImageCallback { public abstract void imageLoaded(Drawable drawable, String imageUrl); } class ImageHandler extends Handler { AsyncImageLoader asyncImageLoader; ImageCallback imageCallback; String imageUrl; public ImageHandler(AsyncImageLoader asyncImageLoader, ImageCallback paramImageCallback, String paramString) { this.asyncImageLoader = asyncImageLoader; this.imageCallback = paramImageCallback; this.imageUrl = paramString; } public void handleMessage(Message paramMessage) { if (this.imageCallback != null) { Drawable localDrawable = (Drawable) paramMessage.obj; // 将图片和图片的URL 传给回调函数,在回调函数中进行相应操作。 imageCallback.imageLoaded(localDrawable, this.imageUrl); } } } class ImageThread extends Thread { private AsyncImageLoader asyncImageLoader; private String imageURL; private ImageHandler imageHandler; public ImageThread(AsyncImageLoader asyncImageLoader, String imageURL, ImageHandler imageHandler) { this.asyncImageLoader = asyncImageLoader; this.imageURL = imageURL; this.imageHandler = imageHandler; } public void run() { Drawable localDrawable = AsyncImageLoader .loadImageFromUrl(this.imageURL); // 将新下载的图片存入imageCache HashMap imageCache = asyncImageLoader.getImageCache(); String str = this.imageURL; SoftReference localSoftReference = new SoftReference(localDrawable); imageCache.put(str, localSoftReference); Message localMessage = this.imageHandler.obtainMessage(0, localDrawable); // 将图片 通过消息发送给hander this.imageHandler.sendMessage(localMessage); } } }
注意这里使用了 SoftReference来缓存图片,允许 GC在需要的时候可以对缓存中的图片进行清理。它这样工作:
l 调用 loadDrawable(ImageUrl, imageCallback),传入一个匿名实现的 ImageCallback接口
l 如果图片在缓存中不存在的话,图片将从单一的线程中下载并在下载结束时通过 ImageCallback回调
l 如果图片确实存在于缓存中,就会马上返回,不会回调 ImageCallback