安卓LruCache

我们都知道安卓系统对内存的消耗的条件是相当苛刻的,一般安卓系统规定每个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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值