Android開源架構Universal-Image-Loader學習三——UsingFreqLimitedMemoryCache源碼閱讀

來源:互聯網
上載者:User

標籤:



Universal-Image-Loader的記憶體緩衝策略

1. 只使用的是強引用緩衝 

  • LruMemoryCache(這個類就是這個開源架構預設的記憶體緩衝類,緩衝的是bitmap的強引用)

2.使用強引用和弱引用相結合的緩衝有

  • UsingFreqLimitedMemoryCache(如果緩衝的圖片總量超過限定值,先刪除使用頻率最小的bitmap)
  • LRULimitedMemoryCache(這個也是使用的lru演算法,和LruMemoryCache不同的是,他緩衝的是bitmap的弱引用)
  • FIFOLimitedMemoryCache(先進先出的緩衝策略,當超過設定值,先刪除最先加入緩衝的bitmap)
  • LargestLimitedMemoryCache(當超過緩衝限定值,先刪除最大的bitmap對象)
  • LimitedAgeMemoryCache(當 bitmap加入緩衝中的時間超過我們設定的值,將其刪除)

3.只使用弱引用緩衝

  • WeakMemoryCache(這個類緩衝bitmap的總大小沒有限制,唯一不足的地方就是不穩定,緩衝的圖片容易被回收掉)


繼承關係:

public class UsingFreqLimitedMemoryCache extends LimitedMemoryCachepublic abstract class LimitedMemoryCache extends BaseMemoryCachepublic abstract class BaseMemoryCache implements MemoryCachepublic interface MemoryCache extends MemoryCacheAware<String, Bitmap>@Deprecatedpublic interface MemoryCacheAware<K, V>

1、先來看MemoryCacheAware:


/* Interface for memory cache*/@Deprecatedpublic interface MemoryCacheAware<K, V> {    /*Puts value into cache by key     * @return true - if value was put into cache successfully;false - if value was not put into cache     */    boolean put(K key, V value);     /** Returns value by key. If there is no value for key then null will be returned. */    V get(K key);     /** Removes item by key */    V remove(K key);     /** Returns all keys of cache */    Collection<K> keys();     /** Remove all items from cache */    void clear();}

2、現在一般使用MemoryCache替代MemoryCacheAware:

MemoryCacheAware源碼:

public interface MemoryCache extends MemoryCacheAware<String, Bitmap> {}

3、BaseMemoryCache 源碼:

/*為memory cache提供一些準系統;提供object的引用(非強引用)儲存*/public abstract class BaseMemoryCache implements MemoryCache {    /** 儲存objects的非強引用,Collections.synchronizedMap保證安全執行緒*/    private final Map<String, Reference<Bitmap>> softMap = Collections.synchronizedMap(new HashMap<String, Reference<Bitmap>>());     @Override    public Bitmap get(String key) {        Bitmap result = null;        Reference<Bitmap> reference = softMap.get(key);        if (reference != null) {            result = reference.get();        }        return result;    }     @Override    public boolean put(String key, Bitmap value) {        softMap.put(key, createReference(value));        return true;    }     @Override    public Bitmap remove(String key) {        Reference<Bitmap> bmpRef = softMap.remove(key);        return bmpRef == null ? null : bmpRef.get();    }     @Override    public Collection<String> keys() {        synchronized (softMap) {            return new HashSet<String>(softMap.keySet());        }    }     @Override    public void clear() {        softMap.clear();    }     /** Creates {@linkplain Reference not strong} reference of value */    protected abstract Reference<Bitmap> createReference(Bitmap value);} 

4、LimitedMemoryCache源碼:

/** * 限定的Cache.提供Object的儲存。所有儲存的bitmap的總記憶體大小不超過限定值 * 註:該cache使用強引用和弱引用來儲存Bitmaps; * 強引用——對於限額內的bitmaps * 弱應用——對於其他的Bitmaps */public abstract class LimitedMemoryCache extends BaseMemoryCache {     private static final int MAX_NORMAL_CACHE_SIZE_IN_MB = 16;    private static final int MAX_NORMAL_CACHE_SIZE = MAX_NORMAL_CACHE_SIZE_IN_MB * 1024 * 1024;     private final int sizeLimit;    /*AtomicInteger,一個提供原子操作的Integer的類,使得操作安全執行緒*/    private final AtomicInteger cacheSize;     /**     * 包含儲存objects的強引用。每個object都添加到最尾端;如果hard cache的大超過了限定值,首端的object將會被刪除     *(但它依然存在在softMap中,而且可以隨時被GC回收)     // 返回一個synchronizes封裝的安全執行緒的List        public static <T> List<T> synchronizedList(List<T> list)*/    private final List<Bitmap> hardCache = Collections.synchronizedList(new LinkedList<Bitmap>());     /**建構函式:sizeLimit單位bytes */    public LimitedMemoryCache(int sizeLimit) {        this.sizeLimit = sizeLimit;        cacheSize = new AtomicInteger();        /**檢測避免sizeLimit值設定過大 */        if (sizeLimit > MAX_NORMAL_CACHE_SIZE) {            L.w("You set too large memory cache size (more than %1$d Mb)", MAX_NORMAL_CACHE_SIZE_IN_MB);        }    }    /**操作成功返回true,操作失敗返回false        先嘗試將Bitmap添加至hard cache,再將其添加至soft cache*/    @Override    public boolean put(String key, Bitmap value) {        boolean putSuccessfully = false;                int valueSize = getSize(value);    //抽象函數,返回Bitmap的大小值        int sizeLimit = getSizeLimit();    //返回sizeLimit        int curCacheSize = cacheSize.get();//返回cacheSize的當前值         /**如果添加的bitmap的size大於sizeLimit,則直接不將其添加至hard cache*/        if (valueSize < sizeLimit) {            /**判斷新添加的Object的valueSize加上當前cache中已有object的curCacheSize超過限定值,則會刪除適當Bitmap*/            while (curCacheSize + valueSize > sizeLimit) {                Bitmap removedValue = removeNext();    //abstract函數,返回需要刪除的下一個Bitmap                if (hardCache.remove(removedValue)) {                    curCacheSize = cacheSize.addAndGet(-getSize(removedValue));                }            }            hardCache.add(value);          //添加到LinkedList<Bitmap>尾部                   cacheSize.addAndGet(valueSize);//即cacheSize+valueSize             putSuccessfully = true;        }        // Add value to soft cache        super.put(key, value);        return putSuccessfully;    }     @Override    public Bitmap remove(String key) {        Bitmap value = super.get(key);        if (value != null) {            if (hardCache.remove(value)) {                cacheSize.addAndGet(-getSize(value));            }        }        return super.remove(key);    }     @Override    publicvoid clear() {        hardCache.clear();        cacheSize.set(0);        super.clear();    }     protected int getSizeLimit() {        return sizeLimit;    }     protected abstract int getSize(Bitmap value);     protected abstract Bitmap removeNext();} 

5、UsingFreqLimitedMemoryCache源碼:(關鍵在於get中更新使用頻率)

/** * Limited {@link Bitmap bitmap} cache. Provides {@link Bitmap bitmaps} storing. Size of all stored bitmaps will not to * exceed size limit. When cache reaches limit size then the bitmap which used the least frequently is deleted from * cache(刪除最少使用頻率的bitmap) * NOTE:使用強引用和弱引用; * 強引用:for limited count of Bitmaps (depends on cache size) * 弱應用:for all other cached Bitmaps */public class UsingFreqLimitedMemoryCache extends LimitedMemoryCache {    /**     * Contains strong references to stored objects (keys) and last object usage date (in milliseconds). If hard cache     * size will exceed limit then object with the least frequently usage is deleted (but it continue exist at     * {@link #softMap} and can be collected by GC at any time)     */    private final Map<Bitmap, Integer> usingCounts = Collections.synchronizedMap(new HashMap<Bitmap, Integer>());     public UsingFreqLimitedMemoryCache(int sizeLimit) {        super(sizeLimit);    }     @Override    public boolean put(String key, Bitmap value) {        if (super.put(key, value)) {            usingCounts.put(value, 0);            return true;        } else {            return false;        }    }     @Override    public Bitmap get(String key) {        Bitmap value = super.get(key);        // 如果value存在,則usageCount+ 1;        if (value != null) {            Integer usageCount = usingCounts.get(value);            if (usageCount != null) {                // 更新value對應的usageCount的值                usingCounts.put(value, usageCount + 1);            }        }        return value;    }     @Override    public Bitmap remove(String key) {        Bitmap value = super.get(key);        if (value != null) {            usingCounts.remove(value);        }        return super.remove(key);    }     @Override    public void clear() {        usingCounts.clear();        super.clear();    }     @Override    protected int getSize(Bitmap value) {        return value.getRowBytes() * value.getHeight();    }     @Override    protected Bitmap removeNext() {        Integer minUsageCount = null;        Bitmap leastUsedValue = null;        Set<Entry<Bitmap, Integer>> entries = usingCounts.entrySet();        synchronized (usingCounts) {            for (Entry<Bitmap, Integer> entry : entries) {               //初始化leastUsedValue                if (leastUsedValue == null) {                    leastUsedValue = entry.getKey();                    minUsageCount = entry.getValue();                } else {                //簡單的比較得到最小值                    Integer lastValueUsage = entry.getValue();                    if (lastValueUsage < minUsageCount) {                        minUsageCount = lastValueUsage;                        leastUsedValue = entry.getKey();                    }                }            }        }        usingCounts.remove(leastUsedValue);        return leastUsedValue;    }     @Override    protected Reference<Bitmap> createReference(Bitmap value) {        return new WeakReference<Bitmap>(value);    }}






Android開源架構Universal-Image-Loader學習三——UsingFreqLimitedMemoryCache源碼閱讀

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.