文章来源:http://blog.csdn.net/guolin_blog/article/details/28863651
DisKLruCache是Google提供的一套硬盘缓存的解决方案(非Google官方编写,但是已获得官方认证)
存储地址
外部存储:/sdcard/Android/data/.../cache
手机存储:Android/data/.../cache
下载DiskLruCache
DiskLruCache类并不在Android API中,所以需要下载,DiskLruCache的源码可以在Google下载
下载后会有很多导入包的问题,本人能力有限没有去解决,可以在git上下载或引入大神处理好的DiskLruCache.java类
https://github.com/JakeWharton/DiskLruCache
implementation 'com.jakewharton:disklrucache:2.0.2'
打开硬盘缓存
DiskLruCache的实例不是new出来的,需要调用open()方法
open(File directory, int appVersion, int valueCount, long maxSize)
接收的参数,directory指定的缓存地址,appVersion指定当前应用程序的版本号,valueCount指定同一个key对应多少个缓存文件,基本都是传1,maxSize指定可以缓存多少个字节的数据。
DiskLruCache diskLruCache = null;
public void open(Context context){
try {
File cacheFile = getDiskCacheDir(context, "bitmap");
//exists方法来检测文件是否存在
if (!cacheFile.exists()){
//mkdir() 如果你想在已经存在的文件夹(D盘下的yyy文件夹)下建立新的文件夹(2010-02-28文件夹),就可以用此方法。此方法不能在不存在的文件夹下建立新的文件夹。假如想建立名字是”2010-02-28”文件夹,那么它的父文件夹必须存在。
//
//mkdirs() 如果你想根据File里的路径名建立文件夹(当你不知道此文件夹是否存在,也不知道父文件夹存在),就可用此方法,它建立文件夹的原则是:如果父文件夹不存在并且最后一级子文件夹不存在,它就自动新建所有路经里写的文件夹;如果父文件夹存在,它就直接在已经存在的父文件夹下新建子文件夹。
cacheFile.mkdirs();
}
diskLruCache= DiskLruCache.open(cacheFile,getVersionId(context),1,10*1024*1024);
} catch (IOException e) {
e.printStackTrace();
}
}
获取文件的缓存地址
public File getDiskCacheDir(Context context,String uniqueName){
String cachePath;
//Environment包含了对SD卡操作的的类,以及常亮状态,获取外部存储目录
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())||Environment.isExternalStorageRemovable()){
//获取应用程序在外部存储的存储目录
cachePath = context.getExternalCacheDir().getPath();
}else{
//获取应用程序自己的缓存目录
cachePath = context.getCacheDir().getPath();
}
return new File(cachePath + File.separator+uniqueName);
}
获取应用程序版本号
public int getVersionId(Context context){
try {
PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
return packageInfo.versionCode;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return 1;
}
写入硬盘缓存
图片地址为 https://img-my.csdn.net/uploads/201309/01/1378037235_7476.jpg,将这张图片下载到缓存中
private void saveResource() {
new Thread(new Runnable() {
@Override
public void run() {
try {
String imageUrl = "https://img-my.csdn.net/uploads/201309/01/1378037235_7476.jpg";
String key = hashKeyForDisk(imageUrl);
DiskLruCache.Editor edit = diskLruCache.edit(key);
if (edit != null){
OutputStream outputStream = edit.newOutputStream(0);
if (downloadUrlToStream(imageUrl,outputStream)){
edit.commit();
}else {
edit.abort();
}
}
//内存中的操作记录同步到日志文件(也就是journal文件)当中
diskLruCache.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
/**
* 下载图片到磁盘缓存
* @param urlString
* @param outputStream
* @return
*/
private boolean downloadUrlToStream(String urlString, OutputStream outputStream){
HttpURLConnection httpURLConnection = null;
BufferedInputStream in = null;
BufferedOutputStream out = null;
try {
URL url = new URL(urlString);
httpURLConnection = (HttpURLConnection) url.openConnection();
in = new BufferedInputStream(httpURLConnection.getInputStream(),8*1024);
out = new BufferedOutputStream(outputStream,8*1024);
int b;
while ((b = in.read())!= -1){
out.write(b);
}
return true;
} catch (IOException e) {
e.printStackTrace();
}finally {
if (httpURLConnection != null){
httpURLConnection.disconnect();
}
try {
if (out != null){
out.close();
}
if (in !=null){
in.close();
}
}catch (IOException e){
}
}
return false;
}
public String hashKeyForDisk(String key){
String cacheKey = null;
try {
MessageDigest mDigest = MessageDigest.getInstance("MD5");
mDigest.update(key.getBytes());
cacheKey = bytestToHextString(mDigest.digest());
} catch (NoSuchAlgorithmException e) {
cacheKey = String.valueOf(key.hashCode());
}
return cacheKey;
}
public String bytestToHextString(byte[] bytes){
StringBuffer sb = new StringBuffer();
for (int i = 0; i < bytes.length; i++) {
String hex = Integer.toHexString(0xFF & bytes[i]);
if (hex.length() == 1){
sb.append("0");
}
sb.append(hex);
}
return sb.toString();
}
调用hashKeyForDisk()方法,获取到对应的key,downloadUrlToStream()中实现下载并写入到缓存中,写入到缓存后需要调用commit()方法才能使写入生效,调用abort()方法表示放弃此次写入。
读取硬盘缓存
读取磁盘缓存DiskLruCache.get()方法
public synchronized Snapshot get(String key)
get()方法传入存入到缓存中的key
private void getResource() {
try {
String imageUrl = "https://img-my.csdn.net/uploads/201309/01/1378037235_7476.jpg";
String key = hashKeyForDisk(imageUrl);
DiskLruCache.Snapshot snapshot = diskLruCache.get(key);
if (snapshot != null){
InputStream is = snapshot.getInputStream(0);
Bitmap bitmap = BitmapFactory.decodeStream(is);
mImage.setImageBitmap(bitmap);
}
} catch (IOException e) {
e.printStackTrace();
}
}
移除缓存
很简单调用remove方法传入对应的key
public synchronized boolean remove(String key)
完成代码为
private void removeResource() {
try {
String imageUrl = "https://img-my.csdn.net/uploads/201309/01/1378037235_7476.jpg";
String key = hashKeyForDisk(imageUrl);
diskLruCache.remove(key);
} catch (IOException e) {
e.printStackTrace();
}
}
其它API
1.size()
返回当前缓存路径下搜友缓存数据的总字节,以byte为单位
2.flush()
将内存中的操作记录同步到日制文件journal中,这个方法非常重要,标准方法是将flush()在onPause()方法中调用
3.close()
和open()是对应的一个方法,将DiskLruCache关闭掉,关闭之后就不能调用DiskLruCache中任何操作方法,close()方法通常在onDestroy()中调用
4.delete()
删除全部的缓存数据
5.setMaxSize()
设置缓存数据的大小