有时会有在加载ListView的时候,包含用户头像或其他需要到网络获取的图片信息,这时如果等待全部获取完成再显示会比较慢,很影响用户体验,所以这时就需要利用到异步加载图片的方法。
今天整理的方法,是用Thread来进行加载,没有利用ThreadPool的方法,后面的方法以后再慢慢学一下吧,先把学会的这个记下来。
具体的效果是,加入每个ListView的项只需要显示一个图片,每张图片都是本地没有的,则先把他们都显示成一张默认的图片(我用的是程序图标),然后开启后台线程去网上取图片,最后再一个一个加载出来。
下面是具体的步骤:
步骤一:写一个异步加载类,我的叫AsyncImageLoader
package com.carter.asynchronousimage;
import java.io.InputStream;
import java.lang.ref.SoftReference;
import java.net.URL;
import java.util.HashMap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
/**
* 异步加载图片类,内部有缓存,可以通过后台线程获取网络图片。首先生成一个实例,并调用loadDrawableByTag方法来获取一个Drawable对象
*/
public class AsyncImageLoader {
/**
* 使用软引用SoftReference,可以由系统在恰当的时候更容易的回收
*/
private HashMap<String, SoftReference<Drawable>> imageCache;
public AsyncImageLoader(){
imageCache = new HashMap<String, SoftReference<Drawable>>();
}
/**
* 通过传入的TagInfo来获取一个网络上的图片
* @param tag TagInfo对象,保存了position、url和一个待获取的Drawable对象
* @param callback ImageCallBack对象,用于在获取到图片后供调用侧进行下一步的处理
* @return drawable 从网络或缓存中得到的Drawable对象,可为null,调用侧需判断
*/
public Drawable loadDrawableByTag(final TagInfo tag, final ImageCallBack callback){
Drawable drawable;
/**
* 先在缓存中找,如果通过URL地址可以找到,则直接返回该对象
*/
if(imageCache.containsKey(tag.getUrl())){
drawable = imageCache.get(tag.getUrl()).get();
if(null!=drawable){
return drawable;
}
}
/**
* 用于在获取到网络图片后,保存图片到缓存,并触发调用侧的处理
*/
final Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
TagInfo info = (TagInfo)msg.obj;
imageCache.put(info.url, new SoftReference<Drawable>(info.drawable));
callback.obtainImage(info);
super.handleMessage(msg);
}
};
/**
* 如果在缓存中没有找到,则开启一个线程来进行网络请求
*/
new Thread(new Runnable() {
@Override
public void run() {
TagInfo info = getDrawableIntoTag(tag);
Message msg = new Message();
msg.what = 0;
msg.obj = info;
handler.sendMessage(msg);
}
}).start();
return null;
}
/**
* 通过传入的TagInfo对象,利用其URL属性,到网络请求图片,获取到图片后保存在TagInfo的Drawable属性中,并