前面说到了内存缓存,接下来就要说说存储缓存。存储缓存采用DiskLruCache,将缓存对象写入文件系统实现缓存。
DiskLruCache源码不能直接使用,需要修改,使用方式有创建查找添加
1.DiskLruCache创建
DiskLruCache.open(File file,1,1,long maxsize);
用open创建,第一个参数是缓存路径,第二个是版本号,第三个是单节点对应的数据个数,一般这两个都设为1,第四个表示的是缓存总大小,超过这个值会清除一部分缓存。
<pre name="code" class="plain">File diskCacheDir = getDiskCacheDir(mContext, "bitmap");
if (!diskCacheDir.exists()) {
diskCacheDir.mkdirs();<span style="white-space:pre"> </span>//如果不存在目录便创建
}
mDiskLruCache = DiskLruCache.open(diskCacheDir, 1, 1,DISK_CACHE_SIZE);
private static final DISK_CACHE_SIZE = 1024*1024*50;<span style="white-space:pre"> </span>//50M
2.添加缓存
DiskLruCache添加是通过Editor完成,Editor表示缓存对象的编辑对象
首先获取图片URL对应的key,在通过key获取Editor对象,DiskLruCache不许晕同时编辑一个缓存对象。
String key = hashKeyFormUrl(url);
DiskLruCache.Editor editor = mDiskLruCache.edit(key);
if (editor != null) {
OutputStream outputStream = editor.newOutputStream(DISK_CACHE_INDEX);
}
通过Editor得到一个文件输出流。
注意:前面设置DiskLruCache第三个参数时设为1,一个节点只能有一个数据,所以DISK_CACHE_INDEX直接设为0。
图片通过这个文件输出流写到文件系统上
public boolean downloadUrlToStream(String urlString,
OutputStream outputStream) {
HttpURLConnection urlConnection = null;
BufferedOutputStream out = null;
BufferedInputStream in = null;
try {
final URL url = new URL(urlString);
urlConnection = (HttpURLConnection) url.openConnection();
in = new BufferedInputStream(urlConnection.getInputStream(),
IO_BUFFER_SIZE);
out = new BufferedOutputStream(outputStream, IO_BUFFER_SIZE);
int b;
while ((b = in.read()) != -1) {
out.write(b);
}
return true;
} catch (IOException e) {
Log.e(TAG, "downloadBitmap failed." + e);
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
MyUtils.close(out);
MyUtils.close(in);
}
return false;
}
除此之外还必须通过editor的commit()来提交写入操作,如果异常,通过Editor的abort()回退整个操作
所以上述的代码改成
String key = hashKeyFormUrl(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();
}
执行提交或回退
3.缓存查找
缓存查找也是把URL转化为key,通过DiskLruCache的get方法得到一个Snapshot对象,再通过Snapshot对象得到缓存文件的输入流,得到Bitmap对象。
注意:为避免OOM,一般不建议直接加载原始图片所以要加载缩略图。
Bitmap bitmap = null;
String key = hashKeyFormUrl(url);
DiskLruCache.Snapshot snapShot = mDiskLruCache.get(key);
if (snapShot != null) {
FileInputStream fileInputStream = (FileInputStream)snapShot.getInputStream(DISK_CACHE_INDEX);
FileDescriptor fileDescriptor = fileInputStream.getFD();
bitmap = mImageResizer.decodeSampledBitmapFromFileDescriptor(fileDescriptor,
reqWidth, reqHeight);
if (bitmap != null) {
addBitmapToMemoryCache(key, bitmap);
}
}
decodeFileDescriptor比decodeFile相比要消耗更小的内存
以上代码来自于《Android开发艺术探究》这本书