DiskLruCache硬盘缓存

DiskLruCache磁盘缓存
1,概述
1,高效加载大图,有效避免OOM,其核心解决思路就是使用LruCache技术,但LruCache只是管理了内存中图片的存储与释放,如果图片从内存中被移除的话,那么又需要从 网络上重新加载一次图片,这显然非常耗时.
2,对此,Google又提供了一套硬盘缓存的解决方案:DiskLruCache磁盘缓存.
3,DiskLruCache并不是由Google官方编写的,所以这个类并没有被包含在Android API当中.
2,应用举例
1,网易新闻
网易新闻中的数据都是从网络上获取的,包括了很多的新闻内容和新闻图片,这些内容和图片在从网络上获取到之后都会存入到本地缓存中,因此即使手机在没有网络的情况下依然能够加载出以前浏览过的新 闻,而使用的缓存技术不用多说,自然是DiskLruCache.
2,缓存的目录
DiskLruCache并没有限制数据的缓存位置,可以自由地进行设定,但是通常情况下多数应用程序都会将缓存的位置选择为/sdcard/Android/data/ /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添加权限:
    
    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

你可能感兴趣的:(DiskLruCache硬盘缓存)