package com.lrumemorycache;
import android.graphics.Bitmap;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* Created by guohongcheng on 2018/4/18.
*/
public class LruMemoryCache {
private final static String TAG = "LruMemoryCache";
private final LinkedHashMap<String, Bitmap> map; // 声明一个LinkedHashMap
private final int maxSize; // 规定的最大存储空间
private int size; // 已经存储的数量大小
// 官方推荐maxSize一般声明为应用分配内存的1/8
// 也可以用剩余内存的1/4
// int maxMemory = (int) Runtime.getRuntime().maxMemory();
public LruMemoryCache(int maxSize) {
this.map = new LinkedHashMap<String, Bitmap>(0, 0.75f, true);
this.maxSize = maxSize;
}
public final Bitmap get(String key) {
if (key == null) {
throw new NullPointerException("get() fail : key == null");
}
synchronized (this) {
return map.get(key);
}
}
public final boolean put(String key, Bitmap value) {
if (key == null || value == null) {
throw new NullPointerException("key == null");
}
synchronized (this) {
size += sizeOf(key, value);
Bitmap previous = map.put(key, value);
if (previous != null) {
size -= sizeOf(key, value);
}
}
trim2Size(maxSize);
return true;
}
/*
* 返回 value 的字节数
* 当entry保存到cache中后,它占用的内存大小保持稳定
* */
private int sizeOf(String key, Bitmap value) {
return value.getRowBytes() * value.getHeight();
}
/*
* 每次插入都会做检查,当插入entry后,超出了map的maxSize,
* 就需要不断删除最老的entry,直到map的大小 小于maxSize
* 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 trim2Size(int maxSize) {
while (true) {
String key;
Bitmap value;
synchronized (this) {
// 如果当前map大小小于0 或者
// 当前map是空,但map大小不为零
// 那么就抛出状态异常
if (size < 0 || (map.isEmpty() && size != 0)) {
throw new IllegalStateException(getClass().getName()
+ ".sizeOf() is reporting inConsistent results!");
}
// map没有超过限制, 或 当前map是空的。 退出while循环
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.
*
* @return the previous value mapped by {@code key}.
*/
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;
}
}
/*
* 在适当的时机调用,清空map
* */
public void clear() {
trim2Size(-1);
}
}
LruMemoryCache 的一种实现
最新推荐文章于 2021-05-29 10:45:57 发布