加载Bitmap的方法:使用BitmapFactory的decodeFile/decodeResource/decodeStream/decodeByteArray可以分别从,文件/资源/输入流/字节数组中加载一个Bitmap。decodeFile/decodeResource会间接调用decodeStream。
通过采样率控制加载出的Bitmap的大小,以提高加载效率:
public static Bitmap decodeSampleBitmapFromResource(Resources resource, int resId,
int reqWidth, int reqHeight) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(resource, resId, options);
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
options.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(resource, resId, options);
}
public static int calculateInSampleSize (BitmapFactory.Options options, int reqWidth, int reqHeight) {
int width = options.outWidth;
int height = options.outHeight;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
int halfWidth = width / 2;
int halfHeight = height / 2;
while (halfHeight / inSampleSize >= reqHeight
&& halfWidth / inSampleSize >= reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
LRU(Least Recently Used):内存缓存LruCache和存储设备缓存DiskLruCache
int cacheSize = 4 * 1024 * 1024; // 4MiB
LruCache bitmapCache = new LruCache(cacheSize) {
protected int sizeOf(String key, Bitmap value) {
return value.getByteCount();
}
}}
如果缓存对象引用的资源需要显式的进行释放,可以复写entryRemoved方法释放资源。
当通过get方法成功访问到一个缓存对象,在LruCache内部会将其移动到队列头部;通过put方法添加缓存时,如果缓存已满,队列最后一个对象就会被删除。可以通过remove方法直接删除一个缓存对象。
LruCache是线程安全的。
2. DiskLruCache
将缓存对象写入文件系统进行缓存。不在sdk中,需另行下载。源码
public static DiskLruCache open(File directory, int appVersion, int valueCount, long maxSize)
throws IOException {
参数:
private static final long DISK_CACHE_SIZE = 1024 * 1024 * 50;
File diskCacheDir = getDiskCacheDir(mContext, "bitmap");
if (!diskCacheDir.exists()) {
diskCacheDir.mkdirs();
}
mDiskLruCache = DiskLruCache.open(diskCacheDir, 1, 1, DISK_CACHE_SIZE);
DiskLruCache.Editor editor = mDiskLruCache.edit(key);
if (editor != null) {
OutputStream out = editor.newOutputStream(0); // valueCount为1,index从0开始
}
将数据写入到该输出流之后,调用editor的commit方法,缓存创建完成:
if (downloadUrlToStream(url, outputStream)) {
editor.commit();
}
DiskLruCache.Snapshot snapshot = mDiskLruCache.get(key);
if (snapshot != null) {
FileInputStream in = (FileInputStream) snapshot.getInputStream(0);
FileDescriptor fd = in.getFD();
bitmap = decodeSampleBitmapFromFD(fd, reqWidth, reqHeight);
if (bitmap != null) {
addBitmapToMemoryCache(key, bitmap);
}
}