文档章节

picasso 之 LruCache

plugin
 plugin
发布于 2015/05/11 14:06
字数 700
阅读 198
收藏 2

Lru是一种页面置换算法,当进程访问的页面不在内存,而且内存已无空闲空间时,系统必须从内存中调出一页送到磁盘的对换区。

调出的这一页到底是哪页呢?Lru就是其中一种算法,称为“最近最久未使用算法”。

从构造方法开始,

 /** Create a cache using an appropriate portion of the available RAM as the maximum size. */
  public LruCache(Context context) {
    this(Utils.calculateMemoryCacheSize(context));
  }
  /** Create a cache with a given maximum size in bytes. */
  public LruCache(int maxSize) {
    if (maxSize <= 0) {
      throw new IllegalArgumentException("Max size must be positive.");
    }
    this.maxSize = maxSize;
    this.map = new LinkedHashMap<String, Bitmap>(0, 0.75f, true);
  }

    初始化了允许最大缓存大小,和LinkedHashMap

    最重要的应该是get,set方法:

@Override public Bitmap get(String key) {
    if (key == null) {
      throw new NullPointerException("key == null");
    }
    Bitmap mapValue;
    synchronized (this) {    
      mapValue = map.get(key);    //根据key从里面取对应的Bitmap

      if (mapValue != null) {    //能取到的话,记录命中次数的hitCount++,返回该Bitmap

        hitCount++;
        return mapValue;
      }
      missCount++;                //未取到的话,记录未命中次数的missCount++

    }
    return null;                //最后返回null,表示没有找到缓存

  }
@Override public void set(String key, Bitmap bitmap) {
    if (key == null || bitmap == null) {
      throw new NullPointerException("key == null || bitmap == null");
    }
    Bitmap previous;
    synchronized (this) {
      putCount++;            
      size += Utils.getBitmapBytes(bitmap);    // 代表缓存大小的size加上新放入bitmap的大小

      previous = map.put(key, bitmap);  //put()返回该key之前对应的bitmap,没有的话,返回null

      if (previous != null) {            
        size -= Utils.getBitmapBytes(previous);    
    //如果之前key确实有对应的bitmap,现在更新了,自然要减去之前的bitmap大小

      }
    }
    trimToSize(maxSize);
  }

   

private void trimToSize(int maxSize) {
    while (true) {
      String key;
      Bitmap value;
      synchronized (this) {
        if (size < 0 || (map.isEmpty() && size != 0)) {
          throw new IllegalStateException(
              getClass().getName() + ".sizeOf() is reporting inconsistent results!");
        }
        if (size <= maxSize || map.isEmpty()) {    //如果现在缓存的大小还没超过限制,就不做处理

          break;
        } 
        /*能执行到这里说明缓存已经超过最大限制了,所以这里应该使用LRU算法,将超过最大缓存大小的部分去掉
          注意:里面的map使用的LinkedHashMap,我们new的时候,是用的有三个参数的构造方法,第三个参数
          true代表按照最近最少使用在前面,false代表按照插入顺序排序。所以,指定为true的时候,就是map使用的就是LRU算法
          这时,我们每次取第一个,每次只删一个,循环下去,知道size <= maxSize
        */
        
        Map.Entry<String, Bitmap> toEvict = map.entrySet().iterator().next();
        key = toEvict.getKey();
        value = toEvict.getValue();
        map.remove(key);
        size -= Utils.getBitmapBytes(value);
        evictionCount++;
      }
}

    

    清空缓存

     /** Clear the cache. */

  public final void evictAll() {

    trimToSize(-1); // -1 will evict 0-sized elements

  }

    还有一个方法,是实现Cache接口里的。清除指定的缓存。

    就是一个个遍历,每个去比较一下

@Override public final synchronized void clearKeyUri(String uri) {

    boolean sizeChanged = false;

    int uriLength = uri.length();

    for (Iterator<Map.Entry<String, Bitmap>> i = map.entrySet().iterator(); i.hasNext();) {

      Map.Entry<String, Bitmap> entry = i.next();

      String key = entry.getKey();

      Bitmap value = entry.getValue();

      int newlineIndex = key.indexOf(KEY_SEPARATOR);

      if (newlineIndex == uriLength && key.substring(0, newlineIndex).equals(uri)) {

        i.remove();

        size -= Utils.getBitmapBytes(value);

        sizeChanged = true;

      }

    }

    if (sizeChanged) {

      trimToSize(maxSize);

    }

  }

    至此,LruCache就看完了。

© 著作权归作者所有

plugin
粉丝 28
博文 28
码字总数 12617
作品 0
淮安
私信 提问
LruCache在美团DSP系统中的应用演进

背景 DSP系统是互联网广告需求方平台,用于承接媒体流量,投放广告。业务特点是并发度高,平均响应低(百毫秒)。 为了能够有效提高DSP系统的性能,美团平台引入了一种带有清退机制的缓存结构...

美团技术团队
2018/12/24
37
0
聊聊dubbo的LRUCache

序 本文主要研究一下dubbo的LRUCache LRUCache dubbo-2.7.2/dubbo-common/src/main/java/org/apache/dubbo/common/utils/LRUCache.java LRUCache继承了LinkedHashMap,其initialCapacity为1......

go4it
06/20
9
0
Android内存优化之内存缓存

什么是缓存? 缓存技术原理就是把用户访问的所有对象看作一个全集,经过算法标记哪些是用户经常访问的对象,把这些对象放到一个集合里,这个集合是全集一个子集,下一次用户再访问的时候会先...

今晚打猴子
2015/08/21
43
0
安卓图片的异步请求及使用LruCache缓存和手机内存两层存储图片,避免重新加载页面带来的重新请求

看到网友的一片技术博客讲解了LruCache的使用,我把它加到了我的项目中,但是加入断点发现,列表上下滑动时,确实可以不用重新加载图片,但是重新打开这个activity或者重新启动应用,LruCach...

bluecoffee
2015/04/03
309
0
Android LRUCache原理及使用(对象软引用不行,使用LRU算法)

> 对象软引用,弱引用 A a = new A(); SoftReference sr = new SoftReference(a); a = sr.get(); > LRUCache原理及使用 在Android中采用LRU算法的常用缓存有两种:LruCache和DisLruCache,分......

desaco
01/25
0
0

没有更多内容

加载失败,请刷新页面

加载更多

只需一步,在Spring Boot中统一Restful API返回值格式与统一处理异常

统一返回值 在前后端分离大行其道的今天,有一个统一的返回值格式不仅能使我们的接口看起来更漂亮,而且还可以使前端可以统一处理很多东西,避免很多问题的产生。 比较通用的返回值格式如下:...

晓月寒丶
昨天
59
0
区块链应用到供应链上的好处和实际案例

区块链可以解决供应链中的很多问题,例如记录以及追踪产品。那么使用区块链应用到各产品供应链上到底有什么好处?猎头悬赏平台解优人才网小编给大家做个简单的分享: 使用区块链的最突出的优...

猎头悬赏平台
昨天
28
0
全世界到底有多少软件开发人员?

埃文斯数据公司(Evans Data Corporation) 2019 最新的统计数据(原文)显示,2018 年全球共有 2300 万软件开发人员,预计到 2019 年底这个数字将达到 2640万,到 2023 年达到 2770万。 而来自...

红薯
昨天
65
0
Go 语言基础—— 通道(channel)

通过通信来共享内存(Java是通过共享内存来通信的) 定义 func service() string {time.Sleep(time.Millisecond * 50)return "Done"}func AsyncService() chan string {retCh := mak......

刘一草
昨天
58
0
Apache Flink 零基础入门(一):基础概念解析

Apache Flink 的定义、架构及原理 Apache Flink 是一个分布式大数据处理引擎,可对有限数据流和无限数据流进行有状态或无状态的计算,能够部署在各种集群环境,对各种规模大小的数据进行快速...

Vincent-Duan
昨天
60
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部