定义LruCache:
LruCache cache = new LruCache<String, List<?>>(maxSize){
@Override
protected int sizeOf(String key, List<?> value){
return EmptyUtil.isEmpty(value) ? 1 : value.size();
}
}
但是在清空缓存的调用cache.evictAll()
的时候偶尔会报错,
new IllegalStateException(cache.sizeOf() is reporting inconsistent results!);
即 LruCache中自己维护的size 和实际存储数据map的size,无法对应。
我们缓存的list中数据存在可用行,我们偶尔会对list中数据进行清理,假如数据entry已经是不可用状态,将会移除这个数据。
List<?> list = cache.get(key);
if (!EmptyUtil.isEmpty(list) && list.size() > 1) {
filterAndRemove(list);
}
也就是这段代码导致出了问题。
由于我们修改了list的size。导致我们在之后向cache中添加数据的时候计算错误。
public final V put(K key, V value) {
if (key == null || value == null) {
throw new NullPointerException("key == null || value == null");
}
V previous;
synchronized (this) {
putCount++;
size += safeSizeOf(key, value);
previous = map.put(key, value);
if (previous != null) {
size -= safeSizeOf(key, previous);//这里出了问题
}
}
if (previous != null) {
entryRemoved(false, key, previous, value);
}
trimToSize(maxSize);
return previous;
}
当我们添加了相同key的数据到cache中时,由于我们修改了list的大小。导致
size -= safeSizeOf(key, previous);
size减去的值并不是list添加的时候的值。 导致了LruCache中的size出现问题。
eg:
List<?> a = new List<String>{};
List<?> b = new List<String>{};
for(int i=0; i<20; i++){
a.add("value:" + i);
b.add("value:" + i);
}
cache.put("key", a); //这时候cache的值为20
a.remove(0);
//当再次添加key为‘key’的值的时候,LruCache计算size为
//size +=b.size(), size-=a.size();
//即size = 20 + 20, size = 40-19;
//从而导致size值为21,但是cache中存储的数据,为b的size 20个。
cache.put("key", b);
当我们清除cache的时候,将value中数据都清除掉,但是size并不为0.从而报错。
class A {
List<?> value;
int size;
public A(List<?> value){
this.value = value;
this.size = EmptyUtil.isEmpty(value)? 1 : value.size();
}
public int getSize(){
return size;
}
public List<?> getValue(){
return value;
}
}