在上一篇我们已经先后介绍了 Bitmap 的高效加载方式、LruCache 以及 DiskLruCache,那么我们就动手来写一个简化版的 ImageLoader 吧!!!
一般来说,一个优秀的 ImageLoader 应该具备如下功能:
- 图片的同步加载
- 图片的异步加载
- 图片的压缩
- 内存缓存
- 磁盘缓存
- 网络拉取
声明一下,这里实现的 ImageLoader 并不是为了写一个框架,而是纯粹的加深下三级缓存以及图片的高效加载而写的一个小Demo。
1、图片压缩功能的实现
图片压缩在上一篇博客中已经做了介绍,这里就不在废话了,为了有良好的设计风格,这里单独抽象了一个类似于完成图片的压缩功能,这个类叫 ImageResizer,它的实现如下:
public class ImageResizer {
private static final String TAG = "ImageResizer";
public ImageResizer() {
}
/**
* 根据指定的资源文件以及指定的宽/高进行等比例缩放
* @param res
* @param resId
* @param reqWidth
* @param reqHeight
* @return
*/
public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resId, options);
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
options.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(res, resId, options);
}
/**
* 根据文件流的文件描述符以及指定的宽/高进行等比例缩放
* @param fileDescriptor
* @param reqWidth
* @param reqHeight
* @return
*
*/
public static Bitmap decodeSampledBitmapFromFileDescriptor(FileDescriptor fileDescriptor, int reqWidth, int reqHeight) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFileDescriptor(fileDescriptor, null, options);
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
Log.e("00000000", reqWidth + "=====" + reqHeight + "======" + options.inSampleSize);
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFileDescriptor(fileDescriptor, null, options);
}
/**
* 根据指定的宽/高进行 2 的指数缩放
*
* @param options
* @param reqWidth
* @param reqHeight
* @return
*/
private static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
final int width = options.outWidth;
int height = options.outHeight;
int inSampleSize = 1;
if (reqHeight > 0 || reqHeight > 0) {
if (width > reqHeight && height > reqHeight) {
final int halfWidth = width / 2;
final int halfHeight = height / 2;
while (halfWidth / inSampleSize >= reqWidth
&& halfHeight / inSampleSize >= reqHeight) {
inSampleSize *= 2;
}
}
}
return inSampleSize;
}
}
2、内存缓存的实现
public class MemoryCache {
private static MemoryCache instance;
private LruCache<String, Bitmap> mMemoryCache;
private MemoryCache() {
//获取当前进程的可用内存
int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
int cacheSize = maxMemory / 8;
mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {
@Override
protected int sizeOf(String key, Bitmap bitmap) {
//完成bitmap对象大小的计算
return bitmap.getRowBytes() * bitmap.getHeight() / 1024;
}
};
}
public static MemoryCache getInstance() {
if (instance == null) {
synchronized (MemoryCache.class) {
if (instance == null) {
instance = new MemoryCache();
}
}
}
return instance;
}
public void addBitmapToMemoryCache(String uri, Bitmap bitmap) {
String key = MD5.hashKeyFormUrl(uri);
mMemoryCache.put(key, bitmap);
}
public Bitmap getBitmapFromMemoryCache(String key) {
return mMemoryCache.get(key);
}
}
没什么好说的,略过…
3、磁盘缓存的实现
public class DiskCache {
private static