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

     

  • 相关阅读:
    Lucene.Net 2.3.1开发介绍 —— 二、分词(一)
    控制‘控制台应用程序’的关闭操作
    详解for循环(各种用法)
    敏捷软件开发
    Sql Server的一些知识点
    在SharePoint 2010 中配置Remote Blob Storage FILESTREAM Provider
    使用LotusScript操作Lotus Notes RTF域
    JOpt Simple 4.5 发布,命令行解析器
    John the Ripper 1.8.0 发布,密码破解工具
    PacketFence ZEN 4.0.1 发布,网络接入控制
  • 原文地址:https://www.cnblogs.com/wjw334/p/7251219.html
Copyright © 2011-2022 走看看