picasso 之 LruCache

Lru是一種頁面置換算法,當進程訪問的頁面不在內存,並且內存已無空閒空間時,系統必須從內存中調出一頁送到磁盤的對換區。java

調出的這一頁究竟是哪頁呢?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);
  }

    初始化了容許最大緩存大小,和LinkedHashMapapp

    最重要的應該是get,set方法:ide

@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++;
      }
}

    

    清空緩存this

     /** Clear the cache. */

  public final void evictAll() {

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

  }

    還有一個方法,是實現Cache接口裏的。清除指定的緩存。code

    就是一個個遍歷,每一個去比較一下排序

@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就看完了。接口

相關文章
相關標籤/搜索