Android DiskLruCache(磁盘缓存)
.1概念
非Google官方编写,但获得官方认证
但是通常情况下多数应用程序都会将缓存的位置选择为 /sdcard/Android/data/<application package>/cache 这个路径。选择在这个位置有两点好处:第一,这是存储在SD卡上的,因此即使缓存再多的数据也不会对手机的内置存储空间有任何影响,只要SD卡空间足够就行。第二,这个路径被Android系统认定为应用程序的缓存路径,当程序被卸载的时候,这里的数据也会一起被清除掉,这样就不会出现删除程序之后手机上还有很多残留数据的问题
DiskLruCache内存缓存的核心是LinkedHashMap,而DiskLruCache的核心是LinkedHashMap和journal日志文件,相当于把journal看作是一块“内存”,LinkedHashMap的value只保存文件的简要信息,对缓存文件的所有操作都会记录在journal日志文件中。
2.代码
首先需要在当前工程下新建 libcore.io包,并将DiskLruCache文件复制进去
1.初使化
/**
* 图片硬盘缓存核心类
*/
private DiskLruCache mDiskLruCache;
//获取图片的缓存路径
File cacheDir= getDiskCacheDir(context,"myappcacheimgs");
if(!cacheDir.exists()){//此路径如果不存在,则创建
cacheDir.mkdirs();
}
//初使化硬盘缓存,不能new 需要使用open方法
//需要4个参数 第一个参数:数据的缓存地址 第二个参数:当前应用程序的版本号
// 第三个参数:指定同一个key可以对应多少个缓存文件 基本都设置成1
// 第四个参数:指定最多可以缓存多少字节的数据
//设置缓存区大小为10M
try{
mDiskLruCache=DiskLruCache.open(cacheDir,getAppVersion(context),1,10*1024*1024);
}catch (IOException ex){
ex.printStackTrace();;
}
/**
* 根据传入的uniqueName获取硬盘缓存的路径地址
* @param context 上下文对象
* @param uniqueName 缓存的文件夹名称
* @return
*/
public File getDiskCacheDir(Context context, String uniqueName){
String cachePath;
//判断sd卡的状态
if(Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) || !Environment.isExternalStorageRemovable()){
cachePath=context.getExternalCacheDir().getPath();//得到 /sdcard/Android/data/<application package>/cache 这个路径
}else{//sd卡不可用的情况下
cachePath=context.getCacheDir().getPath();//得到 /data/data/<application package>/cache
}
return new File(cachePath+File.separator+uniqueName);
}
/**
* 获取当前应用程序的版本号
* @param context
* @return
*/
public int getAppVersion(Context context){
try {
PackageInfo info=context.getPackageManager().getPackageInfo(context.getPackageName(),0);
return info.versionCode;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return 1;
}
2.存入图片
/**
* 写入sd卡缓存
* @param url
* @param bitmap
*/
public void writeToSd(String url,Bitmap bitmap){
String key= null;
try {
//1.对url进行加密
key = encode(url);
//2.判断是否存在,不存在则进行缓存
if(mDiskLruCache.get(key)==null){
//3.根据key得到编辑器对象
DiskLruCache.Editor editor=mDiskLruCache.edit(key);
if(editor!=null){
//4.得到输出流
OutputStream outputStream=editor.newOutputStream(0);
//5.进行图片的压缩
if(bitmap.compress(Bitmap.CompressFormat.JPEG,100,outputStream)){
//6.进行提交
editor.commit();
}else{
//终止提交
editor.abort();
}
//7.刷新
mDiskLruCache.flush();
}
}
} catch (Exception e) {
e.printStackTrace();
}
/**
* 把一个字符串以md5的放肆加密之后返回...因为url路径里面可能存在一些不可用的特殊字符,所以使用这种方式处理一下
* @param string
* @return
* @throws Exception
*/
private String encode(String string) throws Exception {
byte[] hash = MessageDigest.getInstance("MD5").digest(string.getBytes("UTF-8"));
StringBuilder hex = new StringBuilder(hash.length * 2);
for (byte b : hash) {
if ((b & 0xFF) < 0x10) {
hex.append("0");
}
hex.append(Integer.toHexString(b & 0xFF));
}
return hex.toString();
}
3.得到图片
/**
* 通过key从sd卡缓存目录中查找图片
* @param key
* @return
*/
public Bitmap getPicFromSd(String key){
try {
//1.对key进行加密
String imgKey=encode(key);
//2.得到Snapshot对象
DiskLruCache.Snapshot snapshot=mDiskLruCache.get(imgKey);
//3.进行判断
if(snapshot!=null){
//4.得到输入流对象
InputStream inputStream=snapshot.getInputStream(0);
Bitmap bitmap=BitmapFactory.decodeStream(inputStream);
if(bitmap!=null){
//保存至内存缓存
savePicToMemory(key,bitmap);
}
return bitmap;
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}