上一章解分发器的设计:简单图片加载框架的打造(二)-分发器设计RequestQueue
加载器与缓存器的接口都在第一章定好了,这边只需要完成其接口.我们看一下UML图
Loader
Loader我们实现一个实现ILoader的BaseLoader类,这边用到了策略模式,其下有加载本地图片的Loader,加载网络请求的Loader.
BaseLoader类中,需要先去缓存中获取Bitmap,获取到了直接设置,获取不到,就去调用子类的加载方法去加载.
public abstract class BaseLoader implements ILoader {
public static BitmapCache mBitmapCache = SherlockImageLoader.getInstance()
.getImageLoaderConfig()
.getmBitmapCache();
public static Handler handler = new Handler(Looper.getMainLooper());
@Override
public void loadImage(BitmapRequest request) {
/** 从缓存中取bitmap */
Bitmap bitmap = mBitmapCache.get(request);
if (bitmap == null) {
L.i("获取缓存失败,先显示Loading图");
showLoadingImage(request);
bitmap = onLoad(request);
cacheBitmap(request, bitmap);
}
deliveryToUIThread(request, bitmap);
}
/**
* 缓存图片
* @param request
* @param bitmap
*/
private void cacheBitmap(BitmapRequest request, Bitmap bitmap) {
if (request != null && bitmap != null) {
synchronized (BaseLoader.class) {
mBitmapCache.put(request, bitmap);
}
}
}
protected abstract Bitmap onLoad(BitmapRequest request);
/**
* 显示加载中图片
* @param request
*/
private void showLoadingImage(final BitmapRequest request) {
if (request.getDisplayConfig() != null) {
final ImageView imageview = request.getImageView();
if (imageview == null) {
return;
}
handler.post(new Runnable() {
@Override
public void run() {
imageview.setImageResource(request.getDisplayConfig().loadingImage);
}
});
}
}
/**
* 交给主线程显示
* @param request
* @param bitmap
*/
protected void deliveryToUIThread(final BitmapRequest request, final Bitmap bitmap) {
ImageView imageView = request.getImageView();
L.d("deliveryToUIThread imageView = " + imageView);
if (imageView == null) {
return;
}
handler.post(new Runnable() {
@Override
public void run() {
updateImageView(request, bitmap);
}
});
}
private void updateImageView(final BitmapRequest request, final Bitmap bitmap) {
ImageView imageView = request.getImageView();
L.d("更新UI");
if (imageView == null) {
L.d("为空.返回");
return;
}
//加载正常 防止图片错位
if (bitmap != null && imageView.getTag().equals(request.getImageURL())) {
L.d("加载正常");
imageView.setImageBitmap(bitmap);
} else {
L.d("加载失败,TAG不对");
}
//有可能加载失败
if (bitmap == null
&& request.getDisplayConfig() != null
&& request.getDisplayConfig().failedImage != -1) {
L.d("加载失败,显示默认");
imageView.setImageResource(request.getDisplayConfig().failedImage);
}
//监听
//回调 给圆角图片 特殊图片进行扩展
if (request.getCallback() != null) {
request.getCallback().onSuccess(bitmap, request.getImageURL());
}
}
}
缓存策略
缓存直接写了几个实现BitmapCache接口的类就行了.
- RAMCache内存缓存 使用 LruCache<String, Bitmap> mLruCache;
- RomCache磁盘缓存 使用 DiskLruCache
- DoubleCache 即先从内存取,取不到从磁盘取.
举个列子RAM缓存代码
public class RAMCache implements BitmapCache {
private LruCache<String, Bitmap> mLruCache;
public RAMCache() {
int maxSize = (int) (Runtime.getRuntime().maxMemory() / 4);
L.d("RAMCache maxSize: " + maxSize);
mLruCache = new LruCache<String, Bitmap>(maxSize) {
@Override
protected int sizeOf(String key, Bitmap value) {
int size = value.getRowBytes() * value.getHeight();
L.d("size = " + size);
return size;
}
};
}
@Override
public void put(BitmapRequest bitmapRequest, Bitmap bitmap) {
mLruCache.put(bitmapRequest.getImageUriMD5(), bitmap);
}
@Override
public Bitmap get(BitmapRequest request) {
return mLruCache.get(request.getImageUriMD5());
}
@Override
public void remove(BitmapRequest request) {
mLruCache.remove(request.getImageUriMD5());
}
}
调试
好了,到这步图片加载框架基本上完成了,配置的就没写了,具体在代码中看吧,框架还有很多要完善的,不过锻炼一下架构思维是关键.
工程路径,里面还有我准备写的数据库lib,还有httplib,只看ImageLoaderlib即可. https://github.com/Jerey-Jobs/Sherlock
本文作者:Anderson/Jerey_Jobs
博客地址 : http://jerey.cn/
简书地址 : Anderson大码渣
github地址 : https://github.com/Jerey-Jobs