Android之DiskLruCache(缓存工具)

DiskLruCache

       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



本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/295660.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

内核中根据inode得到文件名_聊聊DOS操作系统中的文件系统FAT12

前面我们更多的集中在Linux系统下文件系统的介绍&#xff0c;是时候介绍一下其它文件系统了。今天我们介绍一下Windows操作系统下的文件系统&#xff0c;也就是FAT文件系统。严格的来说其实是DOS的文件系统。今天我们介绍一下FAT最古老的版本&#xff0c;FAT12文件系统的内容。…

改变世界面貌的十个数学公式

全世界只有3.14 % 的人关注了爆炸吧知识1971年5月15日&#xff0c;尼加拉瓜发行了十张一套题为“改变世界面貌的十个数学公式”邮票&#xff0c;由一些著名数学家选出十个以世界发展极有影响的公式来表彰。这十个公式不但造福人类&#xff0c;而且具有典型的数学美&#xff0c;…

Java开源门户

最近在研究门户&#xff0c;先整理一下开源内容 GateIn&#xff1a; 新的开源门户平台&#xff0c;由RedHat JBoss和eXo平台共同打造。目标是结合强大的企业级Java基础设施和直观友好的用户界面&#xff0c;根据客户的需求&#xff0c;提供最佳的开源门户平台的企业级Java基础设…

.NET 6新特性试用 | 最小Web API

前言如果你使用过其他一些轻量级Web框架&#xff0c;比如Node.JS&#xff0c;你就会知道&#xff0c;创建具有最小依赖项的HTTP API是多么简单&#xff1a;var express require(express) var app express()app.get(/, function (req, res) {res.send(hello My IO!) })app.lis…

Android之SparseArray<E>详解

最近编程时&#xff0c;发现一个针对HashMap<Integer, E>的一个提示&#xff1a; 翻译过来就是&#xff1a;用SparseArray<E>来代替会有更好性能。那我们就来看看源码中SparseArray到底做了哪些事情&#xff1a;一、构造从构造方法我们可以看出&#xff0c;它和一般…

WPF/MVVM 快速开发

http://www.codeproject.com/Articles/165368/WPF-MVVM-Quick-Start-Tutorial 这篇文章醍醐灌顶&#xff0c;入门良药啊&#xff01; Introduction Assuming that you have a decent understanding of C#, getting started in WPF isnt too difficult. I started looking at WP…

钢厂冒的白烟到底有没有污染?东北大学教授的试验结果让你大吃一惊

全世界只有3.14 % 的人关注了爆炸吧知识对于大多数人来讲钢厂的污染首先是来自于冒的气体钢铁企业污染严重的时候烟气有黄烟、黑烟、红烟、褐色烟等和这些烟相比一部分人认为钢厂冒的白烟是水蒸气没有污染另一部分则认为白烟也是污染避之而不及钢厂冒的白烟到底有没有污染呢&am…

IE6下margin-left双倍bug问题

熟悉 CSS 盒模型朋友相信对于 IE 双倍浮动边界 BUG 不会陌生&#xff0c;这个 BUG 只会产生在浮动行的第一个浮动元素&#xff08;此处说法不准确&#xff0c;并不是第一个浮动元素&#xff0c;假如浮动的元素在一行显示不下&#xff0c;占用了多行&#xff0c;那么每一行的第一…

基于事件驱动架构构建微服务第11部分:持续集成

原文链接&#xff1a;https://logcorner.com/building-microservices-through-event-driven-architecture-part12-continuous-integration/在本教程中&#xff0c;我将展示如何设置docker持续集成以在docker容器内构建和运行单元测试。因为我将使用kubernetes在容器中运行微服务…

使用Visual Studio 创建可视Web Part部件

使用Visual Studio 创建可视Web Part部件 可视Web Part部件是很强大的Web 部件。它提供内置设计器创建你的用户界面。本文主要解说怎样使用Visual Studio 创建可视Web Part部件.准备&#xff0c;创建一个自己定义列表Stats&#xff0c;加入某些栏目&#xff0c;填充部分数据。当…

如果在我爸的朋友圈当杠精,会挨揍吗?

1 这位爷爷推这么大力是想换老伴了吧&#xff1f;▼2 撞玻璃门撞出心理阴影的狗子▼3 她和她爸交朋友的方式就是以爸的口吻评论她爸的朋友圈▼4 你们还记得那个学鸭子嘟嘴的小可爱吗&#xff1f;▼5 看看狗子委屈的......▼6 去游个泳&#xff0c;结果收获了一群小鸭子▼…

Git的理解和使用

Git介绍 Git&#xff08;the stupid content tracker&#xff09;是一个源自Linux内核项目的源码管理工具。和传统的CVS、SVN不同&#xff0c;git是一个分布式源码管理工具。 Git命令简单说明git init初始化一个本地的代码仓库。git clone从远程复制一个代码仓库。git configgi…

【v3.6.2】iNeuOS工业互联网操作系统,发布实时存储方式:实时存储、变化存储、定时存储,设备振动状态和电能状态监测驱动...

目 录1. 概述... 12. 平台演示... 23. 存储方式... 24. 设备状态和用电状态监控驱动... 31. 概述本次升级主要增加了对设备实时数据的存储方式、设备振动状态驱动和用电状态监控的驱动&#xff0c;并且优化了部分核心代码。2. 平台演示在线演示&…

查询子串_SQL视图、子查询和常见函数的应用

一、视图含义&#xff1a;虚拟表&#xff0c;和普通表一样使用&#xff0c;通过表动态生成的数据。创建语法的关键字是否实际占用物理空间使用视图CREATE VIEW没有&#xff08;只保存了SQL逻辑&#xff09;增删改查&#xff0c;一般不能增删改表CREATE TABLE占用&#xff08;保…

The application could not be verified

2019独角兽企业重金招聘Python工程师标准>>> //调试的时候出现 The application could not be verified删除已安装的app&#xff0c;再Run 转载于:https://my.oschina.net/liuchuanfeng/blog/550025

git之you can‘t overwrite the remote branch问题解决

今天使用smartGit提交代码的时候出现这个错误&#xff0c;如图&#xff0c; remote是远程的意思&#xff0c;branch是分支的意思&#xff0c;you cant overwrite the remote branch英文的意思是我的remote branch被移动位置了&#xff0c;应该选中edit下面的prefrences下面的al…

数据分析和数据挖掘的理论研究必要性

2019独角兽企业重金招聘Python工程师标准>>> 数据分析&#xff0c;并不抽象&#xff0c;传统的数据分析&#xff0c;包括很多。例如信号处理中的DCT&#xff0c;滤波&#xff0c;IDCT变换。由于确定了滤波窗口的特性&#xff0c;使得对一个时间轴上的数据进行了频谱…

这个国家太奇怪了!全球最落后的国家之一,却又是世界上最幸福的国家!

全世界只有3.14 % 的人关注了爆炸吧知识中国和印度之间喜马拉雅山脉附近存在着一个弹丸小国国家人口仅有75万左右国土面积不足4万平方公里这里没有军队只有人们彼此诚挚的信任这里是最快乐的国度也是世间最神秘纯净的世外桃源这里是徒步天堂没有车水马龙的街道和红绿灯没有高楼…

嵌套饼图_旭日图的效率,高到饼图都羡慕

在展示占比情况时&#xff0c;饼图是我们最常用的选择。但是&#xff0c;饼图只能展示单层数据的占比情况&#xff0c;在面对多层级数据时&#xff0c;我们真的要用10个饼图进行可视化吗&#xff1f;不用挠头苦思&#xff0c;今天我们就来看看多个饼图的组合升级版——旭日图是…

Android之BaseAdapter—convertView回收机制与动态控件响应

前言&#xff1a;对于listView的BaseAdapter的派生&#xff0c;难度比较大。最难理解的莫过于getView(int position, View convertView, ViewGroup parent)这个函数是如何产生每条记录的&#xff0c;有些博客中利用holderView&#xff0c;有些博客却没有用&#xff0c;种种方法…