zoukankan      html  css  js  c++  java
  • Android-Universal-Image-Loader完全解析---缓存策略

    参考过的文献:

    http://blog.csdn.net/xiaanming/article/details/27525741

    Android-Universal-Image-Loader versionCode 40 versionName 1.9.5

    http://blog.csdn.net/u012403246/article/details/46770517

    ImageLoader的缓存策略分为 内存缓存和硬盘缓存

    内存缓存:

    LruMemoryCache

    默认缓存,缓存的是bitmap的强引用,超出最大缓存后remove掉最先访问(put执行一次算一次最新访问重新排序,当前对象往后排)的对象 数据结构:LinkedHashMap<key,Bitmap>

    FIFOLimitedMemoryCache

    超出最大缓存后,先进先出原则,remove掉最先加入(put执行后已经存在的对象不会改变位置,直接remove掉位置0对象)的对象 数据结构:LinkedList<Bitmap>

    FuzzyKeyMemoryCache

    永久存储,删除模糊匹配成功的key,如一些场景高清图下载成功后删除对应的缩略图文件
    LargestLimitedMemoryCache

    当超过缓存限定值,先删除最大的bitmap对象
    LimitedAgeMemoryCache

    当超过缓存时间,删除bitmap对象

    LRULimitedMemoryCache

    这个也是使用的lru算法,和LruMemoryCache不同的是,他缓存的是bitmap的弱引用
    UsingFreqLimitedMemoryCache

    超过缓存限定值,删除使用频次最低bitmap对象
    WeakMemoryCache

    这个类缓存bitmap的总大小没有限制,唯一不足的地方就是不稳定,缓存的图片容易被回收掉

    结构图:

    分析LruMemoryCache

    public class LruMemoryCache implements MemoryCache {
    
    	private final LinkedHashMap<String, Bitmap> map;
    
    	private final int maxSize;
    	/** Size of this cache in bytes */
    	private int size;
    
    	/** @param maxSize Maximum sum of the sizes of the Bitmaps in this cache */
    	public LruMemoryCache(int maxSize) {
    		if (maxSize <= 0) {
    			throw new IllegalArgumentException("maxSize <= 0");
    		}
    		this.maxSize = maxSize;
    		this.map = new LinkedHashMap<String, Bitmap>(0, 0.75f, true);
    	}
    
    	/**
    	 * Returns the Bitmap for {@code key} if it exists in the cache. If a Bitmap was returned, it is moved to the head
    	 * of the queue. This returns null if a Bitmap is not cached.
    	 */
    	@Override
    	public final Bitmap get(String key) {
    		if (key == null) {
    			throw new NullPointerException("key == null");
    		}
    
    		synchronized (this) {
    			return map.get(key);
    		}
    	}
    
    	/** Caches {@code Bitmap} for {@code key}. The Bitmap is moved to the head of the queue. */
    	@Override
    	public final boolean put(String key, Bitmap value) {
    		if (key == null || value == null) {
    			throw new NullPointerException("key == null || value == null");
    		}
    
    		synchronized (this) {
    			size += sizeOf(key, value);
    			Bitmap previous = map.put(key, value);
    			if (previous != null) {
    				size -= sizeOf(key, previous);
    			}
    		}
    
    		trimToSize(maxSize);
    		return true;
    	}
    
    	/**
    	 * Remove the eldest entries until the total of remaining entries is at or below the requested size.
    	 *
    	 * @param maxSize the maximum size of the cache before returning. May be -1 to evict even 0-sized elements.
    	 */
    	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;
    				}
    
    				Map.Entry<String, Bitmap> toEvict = map.entrySet().iterator().next();
    				if (toEvict == null) {
    					break;
    				}
    				key = toEvict.getKey();
    				value = toEvict.getValue();
    				map.remove(key);
    				size -= sizeOf(key, value);
    			}
    		}
    	}
    
    	/** Removes the entry for {@code key} if it exists. */
    	@Override
    	public final Bitmap remove(String key) {
    		if (key == null) {
    			throw new NullPointerException("key == null");
    		}
    
    		synchronized (this) {
    			Bitmap previous = map.remove(key);
    			if (previous != null) {
    				size -= sizeOf(key, previous);
    			}
    			return previous;
    		}
    	}
    
    	@Override
    	public Collection<String> keys() {
    		synchronized (this) {
    			return new HashSet<String>(map.keySet());
    		}
    	}
    
    	@Override
    	public void clear() {
    		trimToSize(-1); // -1 will evict 0-sized elements
    	}
    
    	/**
    	 * Returns the size {@code Bitmap} in bytes.
    	 * <p/>
    	 * An entry's size must not change while it is in the cache.
    	 */
    	private int sizeOf(String key, Bitmap value) {
    		return value.getRowBytes() * value.getHeight();
    	}
    
    	@Override
    	public synchronized final String toString() {
    		return String.format("LruCache[maxSize=%d]", maxSize);
    	}
    }

    可以看到这个类中维护的是一个LinkedHashMap,在LruMemoryCache构造函数中我们可以看到,我们为其设置了一个缓存图片的最大值maxSize,并实例化LinkedHashMap, 而从LinkedHashMap构造函数的第三个参数为ture,表示它是按照访问顺序进行排序的,
    我们来看将bitmap加入到LruMemoryCache的方法put(String key, Bitmap value),  第61行,sizeOf()是计算每张图片所占的byte数,size是记录当前缓存bitmap的总大小,如果该key之前就缓存了bitmap,我们需要将之前的bitmap减掉去,接下来看trimToSize()方法,我们直接看86行,如果当前缓存的bitmap总数小于设定值maxSize,不做任何处理,如果当前缓存的bitmap总数大于maxSize,删除LinkedHashMap中的第一个元素,size中减去该bitmap对应的byte数。

    硬盘存储: 

    LruDiskCache //类似于LruMemerayCache,按照访问顺序,超过最大限制删除最先访问的文件

    LimitedAgeDiskCache //按照缓存时间来排序
    UnlimitedDiskCache //无限制 默认策略

    如果我们在ImageLoaderConfiguration中配置了diskCacheSize和diskCacheFileCount,他就使用的是LruDiscCache,否则使用的是UnlimitedDiscCache

     

  • 相关阅读:
    每天一个Linux指令--httpd
    每天一个Linux指令--alias和unalias
    每天一个Linux指令--adduser
    每天一个Linux指令--ls
    VScode 配置c/c++环境(结合各大网站的blog和官方文档)
    关于大数组定义为全局变量和内部变量的一些区别
    关于simplememory theme的设置和感想
    第一次训练赛感受和题解
    短期目标-1
    家事杂谈
  • 原文地址:https://www.cnblogs.com/wjw334/p/7251219.html
Copyright © 2011-2022 走看看