关于DiskLruCache的详细说明请看Android之硬盘缓存DiskLrucache完全解析
今天我们参照<Android之硬盘缓存DiskLrucache完全解析>,来实现一个Demo。
首先,说一下大概步骤流程:
1.需要获得DiskLruCache的对象,这个对象不能通过new的方式创建,而是通过DiskLruCache.open的方法获得:
public static DiskLruCache open(File directory, int appVersion, int valueCount, long maxSize)
第一个参数为缓存路径的File对象、第二个参数为应用程序版本信息,可以通过版本号,来做一些相应的事情,比如清除缓存、第三个参数为每个Key对应的几个Value,一般都设置为1、第四个参数为最大缓存大小。
File directory:.获得包含缓存路径的File对象:
如果设备包含SD卡或者SD卡不可卸载,则路径可以设为:/sdcard/Android/data/<application package>/cache
否则路径设为内部:/data/data/<application package>/cache
public File getDiskCacheDir(Context context, String uniqueName) {
String cachePath;
if (Environment.MEDIA_MOUNTED.equals(Environment
.getExternalStorageState())
|| !Environment.isExternalStorageRemovable()) {
cachePath = context.getExternalCacheDir().getPath();
} else {
cachePath = context.getCacheDir().getPath();
}
// 返回值为拼接后路径的File对象
return new File(cachePath + File.separator + uniqueName);
}
判断File对象中是否包含相应的缓存目录,没有则创建:
try {
File cacheDir = getDiskCacheDir(this, "bitmap");
if (!cacheDir.exists()) {
cacheDir.mkdirs();
}
int appVersion:获取应用程序版本号:
public int getAppVersion(Context context) {
try {
PackageInfo info = context.getPackageManager().getPackageInfo(
context.getPackageName(), 0);
return info.versionCode;
} catch (NameNotFoundException e) {
e.printStackTrace();
}
return 1;
}
2.获取到DiskLruCache对象后,我们就可以对缓存的数据进行操作了,如将数据写入到Disk缓存、读取Disk缓存、擦除缓存、计算缓存总大小等等。
3.写入到Disk缓存:
写入数据用到的类是DiskLruCache.Editor类,此类同样不能通过new的方式创建对象,需要调用如下方法创建对象:
public Editor edit(String key) throws IOException {
return edit(key, ANY_SEQUENCE_NUMBER);
}
此方法传入一个Key值,作为Key/Value。
Key值的获取:
如果将图片地址URL作为Key的话,容易造成问题。因为URL中可能包含一些特殊字符。这里我们可以通过将URL进行MD5编码,也可以产生一个唯一的Key,并且MD5均是由0-F组成。
/*
* 将字符串进行MD5编码1 用来将Key与图片的URL一一对应成MD5码作为KEY
*/
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;
}
/*
* 将字符串进行MD5编码2 用来将Key与图片的URL一一对应成MD5码作为KEY
*/
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();
}
.获得DiskLruCache.Editor对象后,可以通过editor对象获得一个输出流。从网络上获得图片的输入流urlConnection.getInputStream(),将输入流写到Editor创建的输出流中,即保存到Disk缓存中。
/*
* 下载图片并缓存到Disk的线程
*/
public class CacheWriteToDisk implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
try {
String key = hashKeyForDisk(imageUrl);
/*
* DiskLruCache.Editor用来管理缓存数据写入、访问、移除等
*/
DiskLruCache.Editor editor = mDiskLruCache.edit(key);
if (editor != null) {
OutputStream outputStream = editor.newOutputStream(0);
if (downloadUrlToStream(imageUrl, outputStream)) {
editor.commit();
} else {
// 否则终止
editor.abort();
}
}
mDiskLruCache.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/*
* 下载图片并缓存
* urlString:https://img-my.youkuaiyun.com/uploads/201309/01/1378037235_7476.jpg
*/
private boolean downloadUrlToStream(String urlString,
OutputStream outputStream) {
try {
final 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);
}
Log.v("myu", "Dowload is true");
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();
}
}
Log.v("myu", "Dowload is false");
return false;
}
此时我们从网络上下载的图片就已经缓存到Disk中了。
4.读取Disk缓存中的图片:
利用DiskLruCache的 public synchronized Snapshot get(String key) throws IOException 方法,将图片对应的Key传入到这个方法中,可以获得DiskLruCache.Snapshot对象。如果对象不为空,说明存在对应的Value。可以通过Snapshot.getInputStream(0)方法获得它的输入流,然后调用decodeStream(inputStream),将其转化成Bitmap对象。然后绘制UI就可以了。
/*
* 读取缓存
*/
try {
String key = hashKeyForDisk(imageUrl);
DiskLruCache.Snapshot snapShot = mDiskLruCache.get(key);
if (snapShot != null) {
Log.v("myu", "Image in Disk!!!");
InputStream is = snapShot.getInputStream(0);
Bitmap bitmap = BitmapFactory.decodeStream(is);
// 获取缓存的bitmap后,就可以更新UI了
imageView.setImageBitmap(bitmap);
} else {
Log.v("myu", "Image is Null!!!");
// 如果Disk中没有缓存对应的图片,则开启子线程下载图片并缓存到Disk
new Thread(new CacheWriteToDisk()).start();
}
} catch (IOException e) {
e.printStackTrace();
}
5.Disk缓存清除:
调用DiskLruCache的delete()/deleteContents(File)方法,前者是关闭缓存并且删除所有缓存,后者是删除指定路径的缓存内容。
6.获取缓存的大小:
调用DiskLruCache的size()方法。返回的总的字节大小。