从网上找到的,自己整理了下:
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里,这就是内存的二级缓存,有兴趣的童鞋不凡一试。