安卓LruCache

来源:互联网 发布:单片机wcmd是什么 编辑:程序博客网 时间:2024/06/05 19:16

我们都知道安卓系统对内存的消耗的条件是相当苛刻的,一般安卓系统规定每个APP占用的内存不能超过整个系统RunningMemory的1/8之一不然系统会OOM并杀死程序,那么对于每个APP在使用内存时就要谨慎再谨慎。这篇文章主要讲的就缓存工具类-----LruCache。

一.LruCache详解

LruCache 是 Android 的一个内部类,提供了基于内存实现的缓存

LRU 的工作原理,最近使用的会放进队列的头部,最久未使用的放进队列的尾部,会首先删除队尾元素

  • 如果你 cache 的某个值需要明确释放,重写 entryRemoved 方法
  • 如果 key 相对应的 item 丢掉,重写create(),这简化了调用代码,即使丢失了也总会返回。
  • 默认的,我们需要重写 sizeOf 方法
  • 该类是线程安全的
  • 该类不允许空值和空 key
二.LruCache的变量和方法解释


private int size;// 当前大小private int maxSize;// 最大容量private int putCount;// put次数private int createCount;// 创建次数private int evictionCount;// 回收次数private int hitCount;// 命中次数private int missCount;// 未命中次数

resize()

重新计算缓存的大小,里面涉及到了 trimToSize 方法。

trimToSize()

该方法根据 maxSize 来调整内存 cache 的大小,如果 maxSize 传入 -1,则清空缓存中的所有对象。该源码可知,该内部是一个死循环,靠满足相应的条件达到退出的目的

  • 条件1,当当前大小 size 小于 最大容量时,退出
  • 当需要删除的 entry 为空时,会退出

safeSizeOf()

里面涉及到了我们需要复写的方法 sizeOf

entryRemoved()

当 item 被回收或者删掉时调用。该方法当 value 被回收释放存储空间时被 remove 调用,或者替换 item 值时 put 调用,

默认实现什么都没做。每次回收对象就调用该函数,这里参数为 true --为释放空间被删除;false --get、put 或 remove 导致,需要用户考量进行重写。

get()

通过 key 返回相应的 item,或者创建返回相应的 item。相应的 item 会移动到队列的头部,如果 item 的 value 没有被 cache 或者不能被创建,则返回 null。

create()

create 函数是根据 key 来创建相应的 item,但是在 LruCache 中默认返回的是null。因为 LruCache 未记录被回收的数据,这里读者可以重写该 create 函数,为 key 创建相应的 item,这里是需要读者自行设计。请注意,多线程会导致冲突。

put()

put(K key, V value)

remove()

remove(K key)

总结

  • LruCache 封装了 LinkedHashMap,提供了 LRU 缓存的功能;
  • LruCache 通过 trimToSize 方法自动删除最近最少访问的键值对;
  • LruCache 不允许空键值;
  • LruCache 线程安全;
  • LruCache 的源码在不同版本中不一样,需要区分
  • 继承 LruCache 时,必须要复写 sizeOf 方法,用于计算每个条目的大小。



三.DEMO 

ps:里面有些方法在上篇文章安卓AsyncTask详解有写,这里就不写了。

    private LruCache<ImageView, Bitmap> lruCache;    public LruCacheView() {        int maxMemory = (int) Runtime.getRuntime().maxMemory();        int cacheSize = maxMemory / 4;        Logs.e("系统占用内存大小:  " + cacheSize);        // 创建LruCache对象,同时用匿名内部类的方式重写方法        lruCache = new LruCache<ImageView, Bitmap>(cacheSize) {            @Override            protected int sizeOf(ImageView key, Bitmap value) {//return super.sizeOf(key, value);// 在每次存入缓存的时候调用,我们需要直接返回Bitmap value的实际大小                return value.getByteCount();            }        };    }    /*存储数据到LruCache*/    private void addToCache(ImageView img, Bitmap bitmap) {        if (getFromCache(img) == null) {            lruCache.put(img, bitmap);        }    }    /*从LruCache得到数据*/    private Bitmap getFromCache(ImageView img) {        return lruCache.get(img);    }








阅读全文
0 0
原创粉丝点击