DiskLruCache硬盘缓存

DiskLruCache磁盘缓存
1,概述
1,高效加载大图,有效避免OOM,其核心解决思路就是使用LruCache技术,但LruCache只是管理了内存中图片的存储与释放,如果图片从内存中被移除的话,那么又需要从 网络上重新加载一次图片,这显然非常耗时.
2,对此,Google又提供了一套硬盘缓存的解决方案:DiskLruCache磁盘缓存.
3,DiskLruCache并不是由Google官方编写的,所以这个类并没有被包含在Android API当中.
2,应用举例
1,网易新闻
网易新闻中的数据都是从网络上获取的,包括了很多的新闻内容和新闻图片,这些内容和图片在从网络上获取到之后都会存入到本地缓存中,因此即使手机在没有网络的情况下依然能够加载出以前浏览过的新 闻,而使用的缓存技术不用多说,自然是DiskLruCache.
2,缓存的目录
DiskLruCache并没有限制数据的缓存位置,可以自由地进行设定,但是通常情况下多数应用程序都会将缓存的位置选择为/sdcard/Android/data/ <application package(包名)>/cache 这个路径.
好处:
这是存储在SD卡上的,因此即使缓存再多的数据也不会对手机的内置存储空间有任何影响,只要SD卡空间足够就行.
这个路径被Android系统认定为应用程序的缓存路径,当程序被卸载的时候,这里的数据也会一起被清除掉,避免应用卸载后残留垃圾数据.
当SD卡不存在的时候我们设置缓存目录到/data/data/com.netease.newsreader.activity/cache
3,参看网易新闻的缓存目录
包名:
com.netease.newsreader.activity
缓存目录
SD卡中
/sdcard/Android/data/com.netease.newsreader.activity/cache
手机内存中
/data/data/com.netease.newsreader.activity/cache

3,使用前的配置
    AndroidManifest.xml添加权限:
    <uses-permission android:name="android.permission.INTERNET" />
    module中的build.gradle文件配置:
    dependencies {
        compile 'com.jakewharton:disklrucache:2.0.2'
    }
    或者直接将我们下载后的这个类复制到工程中使用.
    我们可以从GitHub上下载其源码:https://github.com/JakeWharton/DiskLruCache
4,使用
    1,创建DiskLruCache实例并且开启缓存功能!
    创建一个DiskLruCache的实例,通过调用它的静态方法:open()
    public static DiskLruCache open(File directory, int appVersion,         int valueCount,long maxSize)  
    参数1:directory指定的是数据的缓存地址,
    参数2:appVersion指定当前应用程序的版本号,
    参数3:valueCount对应缓存数目,
    参数4:maxSize指定缓存多少字节的数据(容量)
    一个非常标准的open()方法
    第三个参数传1,第四个参数通常传入10M的大小就够了,根据自身的情况进行调节

    2,写入缓存的操作
        1,通过DiskLruCache的Editor edit(String key)方法来获取Editor实例:
        keykey将会成为缓存文件的文件名,
        是将图片的URL进行MD5编码作为key,符合文件的命名规则,同时一一对应.
        2,通过Editor的OutputStream newOutputStream(int index)方法获取                  OutputStream流.
        index参数:索引缓存位置.
        3,将输入流InputStream写入到输出流OutputStream中.
        4,通过Editor的commit(),来提交操作写入生效,若写入失败通过Editor的abort()来终止操作.
        5其他(带缓冲区流的回顾)
        BufferedInputStream是带缓冲区的输入流,默认缓冲区大小是8M,能够减少访问磁盘的次数,提高文件读取性能;                       BufferedOutputStream是带缓冲区的输出流,能够提高文件的写入效率。
        BufferedInputStream与BufferedOutputStream分别是FilterInputStream类和          FilterOutputStream类的子类。

    3,读取缓存
        1,通过DiskLruCache的Snapshot get(String key) 获取Snapshot的实例.
        参数key:加密的url.
        2,通过Snapshot的InputStream getInputStream(int index)获取流
        参数:index存放位置索引.
        3,通过BitmapFactory的Bitmap decodeStream(InputStream is)将流转成                   Bitmap.
        4,用ImageView的Bitmap decodeStream(InputStream is)加载图片.

    4,移除缓存
        boolean remove(String key)
        参数key:通过key来删除对应的缓存图片
        注意:这个方法我们并不应该经常去调用它。因为完全不需要担心缓存的数据过多从而占用SD卡太多空间的问题,DiskLruCache会根据我们在调用open()方法时设定          的缓存最大值来自动删除多余的缓存。
        只有你确定某个key对应的缓存内容已经过期,需要从网络获取最新数据的时才该调用remove()方法来移除缓存。

    5, 缓存数据的总字节数
        size()
        这个方法会返回当前缓存路径下所有缓存数据的总字节数,以byte为单位

    6, 将内存中的操作记录同步到日志文件
    flush()这个方法用于将内存中的操作记录同步到日志文件(也journal)当中。
    这个方法非常重要,因为DiskLruCache能够正常工作的前提就是要依赖于journal文件中的内容。
    并不是每次写入缓存都要调用一次flush()方法的,频繁地调用并不会带来任何好处,只会额外增加同步journal文件的时间。
    比较标准的做法就是在Activity的onPause()方法中去调用一次flush()方法就可以了。

    7,close()
    这个方法用于将DiskLruCache关闭掉,是和open()方法对应的一个方法。关闭掉了之后就不能再调用DiskLruCache中任何操作缓存数据的方法,通常只应该     在Activity的onDestroy()方法中去调用close()方法。

    8,缓存数据全部删除
    delete()
    这个方法用于将所有的缓存数据全部删除,比如说网易新闻中的那个手动清理缓存功能,其实只需要调用一下DiskLruCache的delete()方法就可以实现了。
    9,缓存路径
    File getDirectory()

    10,缓存容量
    long getMaxSize()
    
    11,修改缓存容量.
    setMaxSize(long maxSize)

    12,Editor
        set(int index, String value)
        String getString(int index)
        abortUnlessCommitted()
        InputStream newInputStream(int index)
        OutputStream newOutputStream(int index)
        commit()
        abort()
        abortUnlessCommitted()
    13,Snapshot
        close()
        Editor edit()
        InputStream getInputStream(int index)
        getLength(int index) 
        String getString(int index)
    14,Entry
        File getCleanFile(int i)
        File getDirtyFile(int i)
        String getLengths()

    10,journal文件
    DiskLruCache能正常工作的前提就是要依赖于journal文件中的内容.
    第1行:“libcore.io.DiskLruCache”,是DiskLruCache技术的标志固定字符串.
    第2行是DiskLruCache的版本号,这个值是恒为1的。
    第3行是应用程序的版本号,我们在open()方法里传入的版本号是什么这里就会显示什么。
    第4行是valueCount,这个值也是在open()方法中传入的,通常情况下都为1。
    第5行是一个空行。前五行称为journal文件的头.
    第6行是以一个DIRTY前缀开始的,后面紧跟着缓存图片的key。意味着这是一条脏数据。
    每当调用一次DiskLruCache的edit()方法时,都会向journal文件中写入一条DIRTY记录,表示正准备写入一条缓存数据,但不知结果如何。然后调用        commit()方法表示写入缓存成功,这时会向journal中写入一条CLEAN记录,意味着这条“脏”数据被“洗干净了”,调用abort()方法表示写入缓存失败,       这时会向journal中写入一条REMOVE记录。
    也就是说,每一行DIRTY的key,后面都应该有一行对应的CLEAN或者REMOVE的记录,否则这条数据就是“脏”的,会被自动删除掉。
    第7行的那条记录,除了CLEAN前缀和key之外,后面还有一个数字,这是什么意思呢?
    其实,DiskLruCache会在每一行CLEAN记录的最后加上该条缓存数据的大小,以字节为单位。

网易的磁盘缓存文件观察


image.png

journal解析


image.png

网易的cache目录


image.png

网易虚拟机缓存目录
image.png

网易新闻图


image.png

demo地址

DiskLruCacheDemo

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,386评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,939评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,851评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,953评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,971评论 5 369
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,784评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,126评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,765评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,148评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,744评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,858评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,479评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,080评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,053评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,278评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,245评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,590评论 2 343

推荐阅读更多精彩内容