771
魔獸
圖片的內存緩存控製
從網上找到的,自己整理了下:
public class MemoryCache { private static final String TAG = "MemoryCache"; /** * 放入緩存時是個同步操作 * LinkedHashMap構造方法的最後一個參數true代表這個map裏的元素將按照最近使用次數由少到多排列,即LRU * 這樣的好處是如果要將緩存中的元素替換,則先遍曆出最近最少使用的元素來替換以提高效率 */ private Map<String, Bitmap> mCache = Collections.synchronizedMap(new LinkedHashMap<String, Bitmap>(10, 1.5f, true)); /** * 緩存中圖片所占用的字節,初始0,將通過此變量嚴格控製緩存所占用的堆內存 */ private long mSize = 0; /** * 緩存隻能占用的最大堆內存 */ private long mLimit = 1000000; public MemoryCache() { setLimit(Runtime.getRuntime().maxMemory() / 10); } /** * 設置內存使用上限 * @param limit */ public void setLimit(long limit) { mLimit = limit; Log.i(TAG, "MemoryCache will use up to " + (mLimit / 1024. / 1024.) + "MB"); } /** * 獲取內存中緩存的圖片資源 * * @param key * @return */ public Bitmap get(String key) { try { if (! mCache.containsKey(key)) return null; return mCache.get(key); } catch (NullPointerException ex) { return null; } } /** * 將圖片資源緩存到內存 * * @param key * @param bitmap */ public void put(String key, Bitmap bitmap) { try { if (mCache.containsKey(key)) mSize -= getSizeInBytes(mCache.get(key)); mCache.put(key, bitmap); // 累計當前緩存已使用的內存大小 mSize += getSizeInBytes(bitmap); checkSize(); } catch (Throwable th) { th.printStackTrace(); } } /** * 檢測圖片緩存的內存占用 */ private void checkSize() { Log.i(TAG, "cache size=" + mSize + " length=" + mCache.size()); if (mSize > mLimit) { // 先遍曆最近最少使用的元素 Iterator<Map.Entry<String, Bitmap>> iterator = mCache.entrySet().iterator(); while (iterator.hasNext()) { Map.Entry<String, Bitmap> entry = iterator.next(); mSize -= getSizeInBytes(entry.getValue()); iterator.remove(); if (mSize <= mLimit) break; } Log.i(TAG, "Clean cache. New size " + mCache.size()); } } /** * 清空內存緩存 */ public void clear() { mCache.clear(); } /** * 圖片占用的內存 * * @param bitmap * @return */ long getSizeInBytes(Bitmap bitmap) { if (bitmap == null) return 0; return bitmap.getRowBytes() * bitmap.getHeight(); } }
首先限製內存圖片緩衝的堆內存大小,每次有圖片往緩存裏加時判斷是否超過限製大小,超過的話就從中取出最少使用的圖片並將其移除,當然這裏如果不采用這種方式,換做軟引用也是可行的,二者目的皆是最大程度的利用已存在於內存中的圖片緩存,避免重複製造垃圾增加GC負擔,OOM溢出往往皆因內存瞬時大量增加而垃圾回收不及時造成的。隻不過二者區別在於LinkedHashMap裏的圖片緩存在沒有移除出去之前是不會被GC回收的,而SoftReference裏的圖片緩存在沒有其他引用保存時隨時都會被GC回收。所以在使用LinkedHashMap這種LRU算法緩存更有利於圖片的有效命中,當然二者配合使用的話效果更佳,即從LinkedHashMap裏移除出的緩存放到SoftReference裏,這就是內存的二級緩存,有興趣的童鞋不凡一試。
原文:https://www.eoeandroid.com/thread-254866-1-1.html
最後更新:2017-04-03 12:55:04