picasso 之 LruCache
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就看完了。
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。