标签:图片异步加载 线程池 java信号量 imageloader
在《自己动手写android图片异步加载库》系列的第一篇文章中,主要是学习了使用ReferenceQueue来实现一个内存缓存。在这篇文章中主要是介绍在下载很多图片是怎么控制线程和队列。在这版代码里,加入信号量和队列,可以控制下载任务的顺序、可以控制暂停和结束。
代码A:ImageLoader.java
/**
* 图片加载工具类
*
* @author qingtian
* @blog http://blog.csdn.net/bingoSpunky
*/
@SuppressLint("HandlerLeak")
public class ImageLoader {
private int flag = 0;
public static int FLAG_FINISHED_INIT_SECOND_THREAD = 0X1;
private static final int DEFAULT_THREAD_COUNT = 2;
private static final int SUCCESS = 1;
private static final int FAILED = 0;
// config
public int configLoadingImage;// 正在现在时显示的图片id
public int configFailedImage;// 下载失败时显示的资源id
public Type configType = Type.LIFO;// 队列的调度方式
private ExecutorService threadPool;// 线程池
private Tasks task;// 管理任务的队列
// 图片缓存
private LruCache<String, Bitmap> cache;
private Handler mainHandler;// 主线程的handler,修改view
private Handler secondHandler;//
private volatile Semaphore secondSemaphore;// 信号量控制第二条线程发送的正在执行且没执行完的线程的数量==线程池的数量
public ImageLoader() {
this(DEFAULT_THREAD_COUNT);
}
public ImageLoader(int threadNum) {
task = new Tasks();
new Thread() {
public void run() {
Looper.prepare();
secondHandler = new Handler() {
public void handleMessage(android.os.Message msg) {
try {
secondSemaphore.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
threadPool.execute(task.getTask(configType));
};
};
flag |= FLAG_FINISHED_INIT_SECOND_THREAD;
task.mSemaphore.release();
Looper.loop();
};
}.start();
mainHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
ImgBeanHolder holder;
switch (msg.what) {
case SUCCESS:
holder = (ImgBeanHolder) msg.obj;
ImageView imageView = holder.imageView;
Bitmap bm = holder.bitmap;
String uri = holder.uri;
Object tag = imageView.getTag();
if (holder!=null&&holder.listener != null) {
if (tag != null && tag.toString().equals(uri)) {
holder.listener.onSuccess(imageView, true, bm, uri);
} else {
holder.listener.onSuccess(imageView, false, bm, uri);
}
LogUtils.d("加载失败 加载图片 uri:"+holder.uri);
}
break;
case FAILED:
holder = (ImgBeanHolder) msg.obj;
if (holder.listener != null) {
holder.listener.onFailed();
LogUtils.d("加载成功 加载图片 uri:"+holder.uri);
}
break;
}
}
};
threadPool = new ThreadPoolExecutor(threadNum, threadNum, 0,
TimeUnit.SECONDS, new LinkedBlockingDeque<Runnable>());
secondSemaphore = new Semaphore(threadNum);
int maxMemory = (int) Runtime.getRuntime().maxMemory();
cache = new LruCache<String, Bitmap>(maxMemory / 8) {
// 测量Bitmap的大小
@Override
protected int sizeOf(String key, Bitmap value) {
return value.getRowBytes() * value.getHeight();
}
};
}
public void display(ImageView iv, String uri) {
display(iv, uri, new SimpleImageLoaderListener());
}
public void display(final ImageView iv, final String uri,
final ImageLoaderListener imageLoaderListener)
throws RuntimeException {
if (imageLoaderListener == null) {
throw new RuntimeException("imageLoaderListener不能为空");
}
iv.setTag(uri);
showDefalutImage(iv);
task.addTask(flag, new Runnable() {
@Override
public void run() {
LogUtils.d("开始 加载图片 uri:"+uri);
Bitmap bm = cache.get(uri);
if (bm != null) {
LogUtils.d("在内存缓存 加载图片 uri:"+uri);
sendMessageToMainHandler(SUCCESS, bm, iv, uri,
imageLoaderListener);
} else {
ImageSize imageSize = ImageViewUtil.getImageViewWidth(iv);
LogUtils.d("通过网络 加载图片 uri:"+uri);
bm = BitmapUtil.decodeSampledBitmapFromResource(uri,
imageSize.width, imageSize.height);
// bm = BitmapUtil.getImageBitmap(uri);
if (bm != null) {
cache.put(uri, bm);
sendMessageToMainHandler(SUCCESS, bm, iv, uri,
imageLoaderListener);
} else {
sendMessageToMainHandler(FAILED, bm, iv, uri,
imageLoaderListener);
}
}
secondSemaphore.release();
}
});
secondHandler.sendEmptyMessage(0x123);
}
@SuppressWarnings("deprecation")
private static BitmapDrawable mBitmapDrawable = new BitmapDrawable();
public void showDefalutImage(ImageView iv){
if (configLoadingImage != 0) {
iv.setImageResource(configLoadingImage);
}else{
iv.setImageDrawable(mBitmapDrawable);
}
}
public void stop() {
task.stop();
}
public void restart() {
task.start();
}
public void cancel() {
task.cancel();
}
/**
* 向主线程的handler发送message
*/
private void sendMessageToMainHandler(int what, Bitmap bm, ImageView iv,
String uri, ImageLoaderListener imageLoaderListener) {
ImgBeanHolder holder = new ImgBeanHolder();
holder.bitmap = bm;
holder.imageView = iv;
holder.uri = uri;
holder.listener = imageLoaderListener;
Message msg = Message.obtain();
msg.what = what;
msg.obj = holder;
mainHandler.sendMessage(msg);
}
public class ImgBeanHolder {
Bitmap bitmap;
ImageView imageView;
String uri;
ImageLoaderListener listener;
}
}
public class Tasks {
public boolean starting = true;
public enum Type
{
FIFO, LIFO
}
/**
* 引入一个值为1的信号量,防止mPoolThreadHander未初始化完成
*/
public volatile Semaphore mSemaphore = new Semaphore(0);
/**
* 任务队列
*/
private LinkedList<Runnable> mTasks;
public Tasks() {
mTasks = new LinkedList<Runnable>();
}
public synchronized void addTask(int flag, Runnable runnable) {
try {
// 请求信号量,防止mPoolThreadHander为null
if ((flag & ImageLoader.FLAG_FINISHED_INIT_SECOND_THREAD) == 0)
mSemaphore.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
mTasks.add(runnable);
}
public volatile Semaphore startingSemaphore = new Semaphore(0);
/**
* 取出一个任务
*/
public synchronized Runnable getTask(Type type) {
if(!starting){
try {
LogUtils.d("wait()");
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (type == Type.FIFO) {
return mTasks.removeFirst();
} else if (type == Type.LIFO) {
return mTasks.removeLast();
}
return null;
}
public synchronized void start(){
if(!starting){
starting = true;
this.notify();
LogUtils.d("start notify()");
}
}
public synchronized void stop(){
if(starting){
LogUtils.d("stop()");
starting = false;
}
}
/**
* 取消所有任务
*/
public synchronized void cancel(){
mTasks.clear();
}
}
标签:图片异步加载 线程池 java信号量 imageloader
原文地址:http://blog.csdn.net/bingospunky/article/details/45309099