Android 学习笔记--缓存策略

Author Avatar
ChihoPang 12月 20, 2017
  • 在其它设备中阅读本文章

缓存策略是为了避免重复加载带来的效率消耗和流量消耗,进行优化的一种方法。缓存策略的知识点有:算法原理,实现类 LruCache 和 DiskLruCache 的使用方法和底层实现。

参考资料

《开发艺术探索》第 12 章

思维导图

img

主要步骤

  • 缓存添加
  • 缓存获取
  • 缓存删除

    缓存策略

    常用算法:LRU(Least Recently Used),最近最少使用算法,优先淘汰近期最少使用的缓存对象。

LruCache

Android 官方提供的缓存类,线程安全,通过 support-v4 可以兼容到早期 Android 版本。

底层实现

LruCache 是一个泛型类,内部采用 LinkedHashMap 将缓存对象以强引用(直接的对象引用)的方式存储在内存中。

初始化

int maxMemory=(int)(Runtime.getRuntime().maxMemory()/1024);
int cacheSize=maxMemory/8;//缓存总容量大小,此处为当前进程可用内存的 1/8;
mMemoryCache=new LruCache<String,Bitmap>(cacheSize){
    @Override
    protected int sizeOf(String key,Bitmap bitmap){
        //计算缓存大小的方法
        return bitmap.getRowBytes()*bitmap.getHeight()/1024;
    }
};

构造时,需要传入缓存总容量大小,并重写 sizeOf(K,V) 方法,提供每一个缓存对象的大小。不限定单位,两者处于同一单位即可,提供的数值用于 lruCache.trimToSize() 方法,清除最近最少使用的缓存对象。

缓存添加

通过 cache.put(key,value) 即可向缓存添加待缓存对象,向底层 LinkedHashMap 插入值,并清除旧缓存,判断是否需要清除缓存。

缓存获取

通过 cache.get(key) 即可获取缓存。

缓存删除

调用 cache.remove(key) 即可删除特定缓存。

DiskLruCache

用于实现存储设备(磁盘)缓存。为 Android 官方文档推荐的磁盘缓存,但非 Android SDK 一部分。源码地址:https://developer.android.google.cn/samples/DisplayingBitmaps/src/com.example.android.displayingbitmaps/util/DiskLruCache.html#l209

初始化

public static DiskLruCache open(File directory, int appVersion, int valueCount, long maxSize)

通过 DiskLruCache 提供的 open 方法创建,其中 directory 为缓存存储路径;appVersion 一般设置为 1,appVersion 改变时会自动清除之前的缓存文件;valueCount 表示同一个key可以对应多少个缓存文件,一般设置为 1;maxSize 表示缓存的总大小,单位为字节 Byte。

缓存添加

由 Editor 完成,Editor 为一个缓存对象的编辑对象。

  1. 获取 Editor
    通过 cache.edit(key) 获取 editor,若该对象正在被编辑,则返回 null。
  2. 获取 Editor 输出流
    outputStream=Editor.newOutputStream(DISK_CACHE_INDEX),其中,DISK_CACHE_INDEX 指示编辑对象在 key 中的位置,由于构造时一个 key 只对应一个 value,故设置 DISK_CACHE_INDEX 常量为 0 。
  3. 通过输出流写入文件系统
    //该例为缓存网络图片
    in=new BufferedInputStream(urlConnection.getInputStream(),IO_BUFFER_SIZE);
    out =new BufferedOutputStream(outputStream,IO_BUFFER_SIZE);
    int b;
    while((b=in.read())!=-1) out.write(b);
    
  4. 提交或回退 Editor 操作
    提交:editor.commit();
    回退:editor.abort();

缓存获取

  1. 获取快照
    snapShot=cache.get(key);
  2. 获取输入流
    snapShot.getInputStream(DISK_CACHE_INDEX);
    其中,DISK_CACHE_INDEX 指示编辑对象在 key 中的位置,由于构造时一个 key 只对应一个 value,故设置 DISK_CACHE_INDEX 常量为 0 。

缓存删除

public synchronized boolean remove(String key)//删除单一缓存
public void delete()//删除所有缓存

close() 和 flush()

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

flush() 方法用于将内存中的操作记录同步到日志(journal)文件当中。DiskLruCache能够正常工作的前提就是要依赖于journal文件中的内容。比较标准的做法就是在Activity的onPause()方法中去调用一次flush()方法就可以了。