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