DiskLruCache是一个十分好用的android缓存工具,我们可以从GitHub上下载其源码:https://github.com/JakeWharton/DiskLruCache

DiskLruCache所有的数据都存储在/storage/emulated/0/Android/data/应用包名/cache/XXX文件夹中(你也可以修改,但不建议这样做,原因请继续往下看),这个是android系统默认的应用缓存位置,如果应用被删除,这个文件也会一起被删除,避免应用删除后有残留数据的问题。同时,由于数据没有存储在硬盘里,所以不会影响系统性能,在sd卡里,你可以存储任意多数据。
由于DiskLruCache是被final修饰的,因此不可以直接通过new获得它的实例,我们使用它的open方法获得它的一个实例:
public static DiskLruCache open(File directory, int appVersion, int valueCount, long maxSize)
open方法需要四个参数,第一个是缓存文件文件的位置,通过下面的方法可得到:

    private File getDiskCacheDir(Context context, String uniqueName) {String cachePath;//如果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);}

第二个参数是应用程序的版本号,要传入版本号是因为如果应用升级缓存会被清除掉。通过下面的方法可以获得程序的版本号:

    private int getAppVersion(Context context) {try {PackageInfo info = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);return info.versionCode;} catch (NameNotFoundException e) {e.printStackTrace();}return 1;}

第三个参数表示同一个key可以对应多少个缓存文件,一般情况下我们都是传1,这样key和缓存文件一一对应,查找和移除都会比较方便。
第四个参数表示最大可以缓存多少字节的数据。
打开了DiskLruCache之后,我们可以看看怎么向DiskLruCache中缓存数据:
先来看看从网上down一张图片:

    private boolean downloadImg(final String urlStr,final OutputStream outputStream) {HttpURLConnection conn = null;BufferedOutputStream out = null;BufferedInputStream in = null;try {URL url = new URL(urlStr);conn = (HttpURLConnection) url.openConnection();in = new BufferedInputStream(conn.getInputStream(), 8 * 1024);out = new BufferedOutputStream(outputStream, 8 * 1024);int len = 0;while ((len = in.read()) != -1) {out.write(len);}return true;} catch (IOException e) {e.printStackTrace();} finally {if (conn != null)conn.disconnect();try {if (out != null)out.close();} catch (IOException e) {e.printStackTrace();}try {if (in != null)in.close();} catch (IOException e) {e.printStackTrace();}}return false;}

这是一个简单的联网down图片代码,拿到图片后就可以缓存到本地了,但是对于每一个存储资源都需要有一个key,这个key要是唯一的,而且这个key最长120个字符,且只能包括a-z,0-9,下划线以及减号,一次我们可以采用Java中的UUID来得到key,也可以使用MD5加密网址得到一个key,我这里采用md5,方法如下:

public class MD5Util {public final static String md5(String pwd) {//用于加密的字符char md5String[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9','A', 'B', 'C', 'D', 'E', 'F' };try {//使用平台的默认字符集将此 String 编码为 byte序列,并将结果存储到一个新的 byte数组中byte[] btInput = pwd.getBytes();// 获得指定摘要算法的 MessageDigest对象,此处为MD5//MessageDigest类为应用程序提供信息摘要算法的功能,如 MD5 或 SHA 算法。//信息摘要是安全的单向哈希函数,它接收任意大小的数据,并输出固定长度的哈希值。 MessageDigest mdInst = MessageDigest.getInstance("MD5");//System.out.println(mdInst);  //MD5 Message Digest from SUN, <initialized>//MessageDigest对象通过使用 update方法处理数据, 使用指定的byte数组更新摘要mdInst.update(btInput);//System.out.println(mdInst);  //MD5 Message Digest from SUN, <in progress>// 摘要更新之后,通过调用digest()执行哈希计算,获得密文byte[] md = mdInst.digest();//System.out.println(md);// 把密文转换成十六进制的字符串形式int j = md.length;//System.out.println(j);char str[] = new char[j * 2];int k = 0;for (int i = 0; i < j; i++) {   //  i = 0byte byte0 = md[i];  //95str[k++] = md5String[byte0 >>> 4 & 0xf];    //    5  str[k++] = md5String[byte0 & 0xf];   //   F}//返回经过加密后的字符串return new String(str);} catch (Exception e) {e.printStackTrace();return null;}}
}

各位看官在使用的时候记得把md5String[]中大写的字母改为小写,因为key中如果有大写字母验证会不通过。当然,你也可以修改DiskLruCache的源码从而让它支持大写字母,修改的地方:

现在万事俱备,我们来把图片缓存起来,由于联网是好事操作,所以要在新线程中完成,完整的方法如下:

    private void cacheImg() {new Thread(new Runnable() {@Overridepublic void run() {String key = MD5Util.md5(IMGIP);try {DiskLruCache.Editor editor = mDiskLruCache.edit(key);if (editor != null) {OutputStream out = editor.newOutputStream(0);if (downloadImg(IMGIP, out)) {//提交editor.commit();} else {//撤销操作editor.abort();}}/*** 这个方法用于将内存中的操作记录同步到日志文件(也就是journal文件)当中。* 这个方法非常重要,因为DiskLruCache能够正常工作的前提就是要依赖于journal文件中的内容。* 并不是每次写入缓存都要调用一次flush()方法的,频繁地调用并不会带来任何好处,* 只会额外增加同步journal文件的时间。* 比较标准的做法就是在Activity的onPause()方法中去调用一次flush()方法就可以了*/mDiskLruCache.flush();} catch (IOException e) {e.printStackTrace();}}}).start();}

editor.newOutputStream(0);方法有一个参数,查看源码我们知道这个参数必须大于0并且小于valueCount,前文中valueCount我们已经设置为1了,所以这里只能取值0。这个时候打开你的缓存文件夹,/storage/emulated/0/Android/data/应用包名/cache/XXX,里边已经有了我们缓存的数据了:

好了,数据存下来了,接下来就是读取,每一个缓存文件都对应一个key,读取就是根据这个key来读取:

    private void showImg() {String key = MD5Util.md5(IMGIP);  try {DiskLruCache.Snapshot snapShot = mDiskLruCache.get(key);if(snapShot!=null){InputStream is = snapShot.getInputStream(0);Bitmap bitmap = BitmapFactory.decodeStream(is);im.setImageBitmap(bitmap);}} catch (IOException e) {e.printStackTrace();} }

读取的时候我们最先拿到的是一个Snapshot 对象,再根据我们之前传入的参数0拿到缓存文件的流,最后把流转换为图片。

到这里大家可能就明白了,之前的editor.newOutputStream(0);方法为什么会有一个0的参数了,相当于一个标识,读取时也传入参数0才能读到我们想要的数据。(加入我们的key与缓存文件不是一一对应,也就是我们一开始的open方法中传入的不是valueCount的值不是1,那么一个key对应多个缓存文件我们要怎么区分?就是通过这种方式,有兴趣的同学查看源码就一目了然了)。

下来就是清除缓存了,看方法:

    private void clearCache() {String key = MD5Util.md5(IMGIP);try {mDiskLruCache.remove(key);} catch (IOException e) {e.printStackTrace();}  }

根据缓存文件的key,调用remove方法,将该缓存文件移除。

下来是查看缓存大小:

像凤凰新闻客户端中显示缓存大小,这个数值我们可以通过size()方法直接拿到:

    private void getCacheSize() {tv.setText(mDiskLruCache.size()+"");}

大家应该看到了凤凰新闻还有一个功能就是清除缓存,这个功能直接调用delete方法就能实现:

    private void deleteAll() {/*** 这个方法用于将所有的缓存数据全部删除* 其实只需要调用一下DiskLruCache的delete()方法就可以实现了。* 会删除包括日志文件在内的所有文件*/try {mDiskLruCache.delete();} catch (IOException e) {e.printStackTrace();}}

所有功能都完成之后,我们要记得在onDestory方法中关闭DiskLruCache。

    @Overrideprotected void onDestroy() {super.onDestroy();/*** 这个方法用于将DiskLruCache关闭掉,是和open()方法对应的一个方法。* 关闭掉了之后就不能再调用DiskLruCache中任何操作缓存数据的方法,* 通常只应该在Activity的onDestroy()方法中去调用close()方法。*/try {mDiskLruCache.close();} catch (IOException e) {e.printStackTrace();}}

到此,我想大家已经基本会用这个东东了吧。

最后奉上本文源码下载地址http://pan.baidu.com/s/1kTzSHtd

版权声明:本文为博主原创文章,未经博主允许不得转载。若有错误地方,还望批评指正,不胜感激。

转载于:https://www.cnblogs.com/lenve/p/4770527.html

三分钟学会缓存工具DiskLruCache相关推荐

  1. 三分钟学会css3中的flexbox布局

    2019独角兽企业重金招聘Python工程师标准>>> 这篇文章里我们将学习CSS里flexbox布局的几个最重要的概念,通过学习flexbox布局,你会发现以往遇到的所有的关于布局 ...

  2. Juniper 210 密码清不掉_三分钟学会如何找回mysql密码

    一.在测试工作中我们肯定会写一些sq查询语句方便我们验证数据是否正确,从而判断当前软件是否存在缺陷,但是查询的过程中肯定需要我们先连接数据库,如果数据库密码忘记我们就无法完成工作,这里就教会大家如何快 ...

  3. 三分钟学会PS小清新调色教程-萧蕊冰

    今天的PS小教程教你三分钟学会PS小清新调色教程.夏天到了,夏天的阳光很大,拍出的照片都会有一种暖色的感觉,那么我们怎么把一张照片调成日式小清新呢?今天我们就来学一个PS小清新调色教程,让你体验一下日 ...

  4. 【ROM制作工具】如何三分钟学会制作手机线刷包?一键制作线刷包详细教程

    如何在最短的时间内制作一款手机线刷包让卡顿的手机线刷回官方?线刷回官方的手机刷机包在制作时有什么样的技巧?接下来将和大家分享一下如何在三分钟制作一款手机线刷包! 一键制作线刷包详细教程 准备工作: 首 ...

  5. WORD如何设置打印? 三分钟学会WORD打印技巧

    我们在办公的时候,很多人时常会需要打印各种各样的文件,很多人都只知道,去打印当前页,或者是整个文档,但在Word打印中也有很多不同的技巧,那么Word如何设置打印?今天呢就来给大家分享一下Word打印 ...

  6. 三分钟学会渗透测试——信息收集

    什么是信息收集 信息收集主要是收集服务器的配置信息和网站的敏感信息,主要包括域名信息.子域名信息.目标网站信息.目标网站真实IP.目录文件.开放端口和服务.中间件信息等等.在进行渗透测试之前,第一步也 ...

  7. 三分钟学会给任何电脑完整重装系统!新手必看!以win10为例

    小白们,不论你电脑是什么型号,状态如何,都可以按照以下流程操作,简单易上手. 由于本人电脑(联想拯救者)从刚开始使用就经常莫名其妙重启,斟酌之后选择重装系统.学习到实践成功,为时半天.在此和大家分享一 ...

  8. 职场神器:只需三分钟,AI工具让我变成插画师

    绘画技能 一般来说,搞技术的,写文章的,在绘画的这棵技能树上的加点往往都是零. 而且绘画和音乐这些技能往往是需要一定天赋的,它不像写代码和开挖机,后两者往往经过培训以后人人都能学会,而前两者没有一点天 ...

  9. 三分钟学会.NET微服务之Polly

    熔断降级是一个非常重要的概念,我们先说一下什么是熔断降级,咱们都知道服务发现,一个有问题的服务器没来得急注销过一会就崩溃掉了,那么我们的请求就有可能访问一个已经崩溃的服务器,那么就会请求失败,因为已经 ...

最新文章

  1. P1276 校门外的树(增强版)(线段树)(校门三部曲)难度⭐⭐⭐
  2. 升级EXCHANGE2010到2013(A)
  3. 【解决方案】VMWare拖动窗口后有黑色边框(分辨率自适应问题)
  4. HihoCode1721删除一个字符之后是回文字符串
  5. wxWidgets:使用事件
  6. 51nod 1557 两个集合 (严谨的逻辑题)
  7. 神舟电脑冲击创业板失败 首发未获证监会通过
  8. Python模块:bisect二分算法模块
  9. windows下安装maven后运行:mvn help:system报错
  10. DPI/DFI/端口识别技术
  11. CentOS 6.5 安装Redis并设置开机自启动
  12. 干货:一个案例看懂“结巴”分词(Jieba),入行NLP必备
  13. 详细介绍光纤跳线接口类型PC, APC, UPC
  14. 【编译原理】语言认知之Java、Python、C++快速排序三者运行效率与开发效率比较
  15. 制程与良率,谁才是芯片厂商的竞赛底牌?
  16. 华为cpe虚拟服务器,你真的看懂它了吗?华为5G CPE Pro深度体验
  17. python3计算行列式的值(运用拉普拉斯展开法递归实现)
  18. FreeRTOS内核——任务与任务切换
  19. wincc 数据库的连接方法
  20. Java面试题集(86-115)

热门文章

  1. redisTemplate设置key零点过期,生成自增的单号
  2. php获取网络文件的几种方式,PHP如何实现获取网络上的文件?
  3. 改变图标颜色_LOL设计师宣布修改装备图标:提高清晰度、颜色差异化
  4. 数据库:MySQL、SqlServer、Oracle对比
  5. Dataway让 Spring Boot 开发变得更高效!
  6. Linux进程命令PS用法笔记
  7. ctrl z撤销后如何恢复_回收站清空后数据如何恢复?
  8. net以execl做数据库_[原创]Net实现Excel导入导出到数据库(附源码)
  9. mongodb数组字段prefix匹配返回
  10. Appium使用Python运行appium测试的实例