2019独角兽企业重金招聘Python工程师标准>>>
原版程序出处未知,不知道是谁写的了,我在原有的基础上现在做一些改进优化
1.增加线程池功能,限制通知下载的线程数,
但是还有一些缺陷,
1.缓存的清理,大量图片之后的缓存策略,比如缓存太多之后,清理一些使用次数比较少的缓存图片
2.对于同一张图片,如果还没存在图片,那么在同一时间可以开启很多个对这张图片的下载任务,此处可以继续优化,后面有时间了再做了
public class AsyncImageLoader {
private static final String TAG = "AsyncImageLoader";
private ThreadPoolExecutor mPoolExecutor;
private HashMap> imageCache;
private Handler mMainThreadHandler;
/**
* 创建一个异步图片加载器,默认最大5个工作线程,最大等待队列20
*/
public AsyncImageLoader() {
this(5, 20);
}
/**
* 创建一个异步图片加载器,当等待下载的图片超过设置的最大等待数量之后,会从等待队列中放弃一个最早加入队列的任务
*
* @param maxPoolSize 最大工作线程数
* @param queueSize 最大等待数
*/
public AsyncImageLoader(int maxPoolSize, int queueSize) {
this(2, maxPoolSize, 3, TimeUnit.SECONDS, new LinkedBlockingQueue(queueSize),
new ThreadPoolExecutor.DiscardOldestPolicy());
}
/**
* 自定义线程池的加载器,请参考:{@link ThreadPoolExecutor}
*
* @param corePoolSize
* @param maximumPoolSize
* @param keepAliveTime
* @param unit
* @param workQueue
* @param handler
*/
public AsyncImageLoader(int corePoolSize, int maximumPoolSize, long keepAliveTime,
TimeUnit unit, BlockingQueue workQueue, RejectedExecutionHandler handler) {
imageCache = new HashMap>();
mPoolExecutor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit,
workQueue, handler);
mMainThreadHandler = new Handler(Looper.getMainLooper());
}
/**
* 异步加载一张图片
*
* @param imageUrl
* @param imageCallback
*/
public void loadDrawable(final String imageUrl, final ImageCallback imageCallback) {
if (imageCache.containsKey(imageUrl)) {
SoftReference softReference = imageCache.get(imageUrl);
Drawable drawable = softReference.get();
if (drawable != null) {
LogUtils.d(TAG, "load image from cache url:" + imageUrl);
imageCallback.onLoaded(drawable);
return;
}
}
LoadImageTask task = new LoadImageTask(imageUrl, this, mMainThreadHandler, imageCallback);
mPoolExecutor.execute(task);
}
/**
* 停止线程池运行,停止之后,将不能在继续调用 {@link #loadDrawable(String, ImageCallback)}
*/
public void shutdown() {
mPoolExecutor.shutdown();
imageCache.clear();
}
private void cache(String url, Drawable drawable) {
imageCache.put(url, new SoftReference(drawable));
}
/**
* 下载任务
*
*/
private static final class LoadImageTask implements Runnable {
private Handler mHandler;
private ImageCallback mCallback;
private AsyncImageLoader mLoader;
private String mPath;
/**
* @param imgPath 要下载的图片地址
* @param loader 图片加载器
* @param handler 主线程Handler
* @param imageCallback 图片加载回调
*/
public LoadImageTask(String imgPath, AsyncImageLoader loader, Handler handler,
ImageCallback imageCallback) {
LogUtils.d(TAG, "start a task for load image:" + imgPath);
this.mHandler = handler;
this.mPath = imgPath;
this.mLoader = loader;
this.mCallback = imageCallback;
}
@Override
public void run() {
URL url;
InputStream is = null;
try {
url = new URL(mPath);
URLConnection conn = url.openConnection();
conn.connect();
is = conn.getInputStream();
final Drawable drawable = Drawable.createFromStream(is, "src");
mLoader.cache(mPath, drawable);
mHandler.post(new Runnable() {
@Override
public void run() {
LogUtils.d(TAG, "load image success:" + mPath);
mCallback.onLoaded(drawable);
}
});
} catch (final Exception e) {
LogUtils.e(TAG, e.getMessage() + "", e);
mHandler.post(new Runnable() {
@Override
public void run() {
LogUtils.d(TAG, "load image failed:" + mPath);
mCallback.onError(e);
}
});
}
}
}
/**
* 回调接口,在主线程中运行
*
*/
public static interface ImageCallback {
/**
* 加载成功
*
* @param imageDrawable 下载下来的图片
*/
public void onLoaded(Drawable drawable);
/**
* 加载失败
*
* @param e 异常
*/
public void onError(Exception e);
}
}