圖片的內存緩存控製
從網上找到的,自己整理了下:
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