概要:
ImageLoader,图片加载类。在Android中经常使用到图片加载。所以一个好的图片的加载类
对一个优秀的app非常重要。本文中是一个自定义的ImageLoader,是主要涉及两个方面:
一,图片的高效加载,主要通过BitmapFactory.Options来缩放图片。我们需要加载的图片如果
大于我们展示图片的控件大小,就会造成内存的浪费。这时我们可以通过Options.inSampleSize来
设置图片缩小的倍数。
二,图片的缓存策越,如果每次都从需要的图片都从网络中获取,会浪费用户的流量,而且不高效。
这里使用LruCache实现内存缓存。DiskLruCache实现磁盘缓存。
分析:
一,图片的高效的加载。
我们在使用BitmapFactory加载图片是,会直接或间接的使用Option。通过设定Option.inSampleSize
来控制加载图片的大小。在Android官方文档中,inSampleSize推荐为2的指数,例如有一张1024*1024*4
(4MB)的图片,当inSampleSize=2时,加载后的Bitmap为512*512*4(1MB),所占内存为原来的1/4。
二,图片的缓存策越,我们加载图片的策越:
1,读取内存缓存,先从内存缓存(MemoryLRUCache)中,查找所需图片。不为null则返回。为null则
执行下一步。
2,读取本地缓存,从磁盘缓存(DiskLRUCache)中,查找所需图片,不为nulll则返回,并将Bitmap添加
到内存缓存(MemoryLRUCache),为nul则执行下一步。
3,读取网络资源,从网络中下载图片到本地即磁盘缓存,然后读取本地缓存。
应用:
一,高效加载图片。
1,从resource中加载图片。
public Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight) {
final BitmapFactory.Options options = new BitmapFactory.Options();
// 第一次加载只获取图片的信息
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resId, options);
// 计算inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// 正式加载Bitmap
options.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(res, resId, options);
}
2,从文件流中加载图片。
/**
* 不能直接对文件流做如下操作,因为两次的decodeStream会影响文件的位置属性
* 导致第二次decodeStream的返回为null,所以中转一下
* FileDescriptor fileDescriptor = FileInputStream.getFD();
*/
public Bitmap decodeSampledBitmapFromFileDescriptor(FileDescriptor descriptor, int reqWidth, int reqHeight) {
final BitmapFactory.Options options = new BitmapFactory.Options();
//从文件信息中提取高宽信息
options.inJustDecodeBounds = true;
BitmapFactory.decodeFileDescriptor(descriptor, null, options);
//计算inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
//正式加载Bitmap
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFileDescriptor(descriptor, null, options);
}
3,计算inSampleSize。
public int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
if (reqWidth == 0 || reqHeight == 0) {
return 1;
}
final int width = options.outWidth;
final int height = options.outHeight;
Log.i(tag, "outOption: height:" + height + ",widht:" + width);
int inSampleSize = 1;
if (width > reqWidth && height > reqHeight) {
int halfWith = options.outWidth / 2;
int halfHeight = options.outHeight / 2;
while (halfWith / inSampleSize >= reqWidth && halfHeight / inSampleSize >= reqHeight) {
inSampleSize *= 2;
}
}
Log.i(tag, "sampleSize:" + inSampleSize);
return inSampleSize;
}
二,图片的缓存策越
1,读取内存缓存
private Bitmap loadBitmapFromMemoryCache(String url) {
String key = hashKeyFromUrl(url);//有个加密算法
return getBitmapFromMemoryCache(key);
}2,读取本地缓存
/**
* 从磁盘中读取Bitmap,并将其添加到内存缓存
*
*/
private Bitmap loadBitmapFromDiskLruCache(String url, int reqWidth, int reqHeight)
throws IOException {
Log.w(tag, "loadBitmapFromDiskLruCache");
if (Looper.myLooper() == Looper.getMainLooper()) {
Log.w(tag, "load bitmap from ui thread, it is not recommended");
}
if (mDiskLruCache == null) {
return null;
}
Bitmap bitmap = null;
String key = hashKeyFromUrl(url);
DiskLruCache.Snapshot snapshot = mDiskLruCache.get(key);
if (snapshot != null) {
FileInputStream inputStream = (FileInputStream) snapshot.getInputStream(DISK_CACHE_INDEX);
FileDescriptor descriptor = inputStream.getFD();
bitmap = mImageResizer.decodeSampledBitmapFromFileDescriptor(descriptor, reqWidth, reqHeight);
if (bitmap != null) {
addBitmapToMemoryCache(key, bitmap);
}
}
return bitmap;
}
3,读取网络资源
/**
* 读取网络资源并将它写入磁盘缓存
*/
private Bitmap loadBitmapFromHttp(String url, int reqWidth, int reqHeight) throws IOException {
if (Looper.myLooper() == Looper.getMainLooper()) {
throw new RuntimeException("can not visit network from ui thread");
}
if (mDiskLruCache == null) {
return null;
}
String key = hashKeyFromUrl(url);
DiskLruCache.Editor editor = mDiskLruCache.edit(key);
if (editor != null) {
OutputStream outputStream = editor.newOutputStream(DISK_CACHE_INDEX);
if (downloadUrlToStream(url, outputStream)) {
editor.commit();
} else {
editor.abort();
}
mDiskLruCache.flush();
}
return loadBitmapFromDiskLruCache(url, reqWidth, reqHeight);
}
792

被折叠的 条评论
为什么被折叠?



