DiskLruCache 不同于LruCache,LruCache是将数据缓存到内存中去,而DiskLruCache是外部缓存,例如可以将网络下载的图片永久的缓存到手机外部存储中去,并可以将缓存数据取出来使用,DiskLruCache不是google官方所写,但是得到了官方推荐,DiskLruCache没有编写到SDK中去,如需使用可直接copy这个类到项目中去。
- DiskLruCache的创建
- DiskLruCache缓存
- DiskLruCache的读取
- DiskLruCache删除
使用前添加依赖:
implementation 'com.jakewharton:disklrucache:2.0.2'
缓存:
代码如下:
/**
* 保存要缓存的数据
* @param path
*/
public void saveCacheData(String path){
try {
String key = hashKeyForDisk(path);
DiskLruCache.Editor editor = mDiskLruCache.edit(key);
if (editor != null) {
OutputStream outputStream = editor.newOutputStream(0);
if (downloadUrlToStream(path, outputStream)) {
editor.commit();
} else {
editor.abort();
}
}
mDiskLruCache.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 获取保存的数据
* @param key
* @return
*/
public InputStream getCacheData(String key){
try{
key = hashKeyForDisk(key);
DiskLruCache.Snapshot snapshot = mDiskLruCache.get(key);
InputStream inputStream = snapshot.getInputStream(0);
return inputStream;
}catch (Exception e){
}
return null;
}
根据URL下载一个Json数据并把它写到输出流outputstream中:
/**
* 根据URL下载一个Json数据并把它写到输出流outputstream中
* @param urlString
* @param outputStream
* @return
*/
private boolean downloadUrlToStream(String urlString, OutputStream outputStream) {
HttpURLConnection urlConnection = null;
BufferedOutputStream out = null;
BufferedInputStream in = null;
try {
URL url = new URL(urlString);
urlConnection = (HttpURLConnection) url.openConnection();
in = new BufferedInputStream(urlConnection.getInputStream(), 8 * 1024);
out = new BufferedOutputStream(outputStream, 8 * 1024);
int b;
while ((b = in.read()) != -1) {
out.write(b);
}
return true;
} catch (final IOException e) {
e.printStackTrace();
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
try {
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
} catch (final IOException e) {
e.printStackTrace();
}
}
return false;
}
- directory表示磁盘缓存的存储路径
缓存目录没有具体限制,可以根据需求自己的定义。一般来说,可以选择SD卡上的/sdcard/Android/data/<application package>/cache
目录,这个目录是Android系统指定的应用程序缓存目录,当应用卸载时,缓存也会被系统清除;当然还可以选择sd卡上的其他目录,也可以选择data下的当前应用目录。当然,一个严禁的程序还要考虑SD卡是否存在等。 - appVersion表示应用的版本号
当appVersion改变时,之前的缓存都会被清除,所以如非必要,我们为其指定一个1,不再改变即可 - valueCount表示单个节点对应的数据个数,也就是同一个key可以对应多少个缓存文件,一般来说我们都选取1.
- maxSize缓存的总大小。
上面已经下载了数据,接着初始化DiskLruCache,并使用DiskLruCache.Editor准备缓存:
DiskLruCache mDiskLruCache=null;
public MyDiskLruCache(Context context) {
try {
File cacheDir = getDiskCacheDir(context, "MibuBean");
if (!cacheDir.exists()){
//创建层级文件
cacheDir.mkdirs();
}
mDiskLruCache=DiskLruCache.open(cacheDir,getAppVersion(context),1,10*1024*1024);
} catch (IOException e) {
e.printStackTrace();
}
}
上面保存数据代码中有个hashKeyForDisk()方法,其作用是把图片URL经过MD5加密生成唯一的key值,避免了URL中可能含有非法字符问题,hashKeyForDisk()代码如下:
/**
* 把URL经过MD5加密生成唯一的key值,
* 避免了URL中可能含有非法字符问题
* @param key
* @return
*/
public String hashKeyForDisk(String key) {
String cacheKey;
try {
final MessageDigest mDigest = MessageDigest.getInstance("MD5");
mDigest.update(key.getBytes());
cacheKey = bytesToHexString(mDigest.digest());
} catch (NoSuchAlgorithmException e) {
cacheKey = String.valueOf(key.hashCode());
}
return cacheKey;
}
private String bytesToHexString(byte[] bytes) {
StringBuilder sb = new StringBuilder();
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();
}
缓存数据调用:
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().get().url(path).build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
//获取数据
try {
InputStream data = myDiskLruCache.getCacheData(path);
String result = new String(ByteStreams.toByteArray(data));
initData(result);
} catch (IOException e1) {
e1.printStackTrace();
}
}
@Override
public void onResponse(Call call, Response response) throws IOException {
//存入数据
MyDiskLruCache myDiskLruCache = new MyDiskLruCache(getContext());
myDiskLruCache.saveCacheData(path);
String string = response.body().string();
//Okhttp框架解析,该代码就不展示了
initData(string);
}
});