android缓存Lrucahe

来源:互联网 发布:大数据面临的问题 编辑:程序博客网 时间:2024/06/05 14:18

LruCache是android提供的本地缓存类,在3.1版本后的Android.jar中utils目录下,3.1版本之前可使用support-v4包,也是在utils目录下

  • 先列一下lru成员

可以看到内部数据存储使用LinkedHashMap,作为再次封装的数据结构,LruCache提供操作方法get(),put(),remove(),resize()等public方法以及获取信息相关的size()等public方法

需要注意的是三个 protected方法create()、entryRemove()和sizeOf();

引用源码里的注释:


 <p>If your cached values hold resources that need to be explicitly released,* override {@link #entryRemoved}.
如果缓存的对象指向需要主动释放的资源,比如最常用的Bitmap对象,就需要重写该方法来完成资源释放等清理工作** <p>If a cache miss should be computed on demand for the corresponding keys,* override {@link #create}. This simplifies the calling code, allowing it to* assume a value will always be returned, even when there's a cache miss.*
如果考虑对应键值未命中的情况,可以重写create赋给一个默认值或其他;这使得调用端代码能够简化,不论是否命中,都能拿到返回值;默认返回null
* <p>By default, the cache size is measured in the number of entries. Override* {@link #sizeOf} to size the cache in different units. For example, this cache* is limited to 4MiB of bitmaps:
默认缓存大小是以缓存对象个数来计数的,可以通过重写sizeof方法自定义缓存大小的单位
  • 方法实现  
1、get方法
/**
* Returns the value for {@code key} if it exists in the cache or can be 
* created by {@code #create}. If a value was returned, it is moved to the
 * head of the queue. This returns null if a value is not cached and cannot 
* be created. */
public final V get(K key) {   
 if (key == null) {        
throw new NullPointerException("key == null");   
 }
    V mapValue;    
synchronized (this) {      
  mapValue = map.get(key);     
   if (mapValue != null) {          
  hitCount++;          
  return mapValue;        }      
  missCount++;    }   
 /*     * Attempt to create a value. This may take a long time, and the map    
 * may be different when create() returns. If a conflicting value was     
* added to the map while create() was working, we leave that value in     
* the map and release the created value.     */   
 V createdValue = create(key);    
if (createdValue == null) {        
return null;    }   //如果用户覆写了create方法,可能会执行以下代码    
synchronized (this) {     
   createCount++;      
  mapValue = map.put(key, createdValue);//返回的是key对应的旧值        
if (mapValue != null) {           
 // There was a conflict so undo that last put        
    map.put(key, mapValue);//如果对应键已经有值了,再把旧值放回去    
    } else {          
  size += safeSizeOf(key, createdValue);    
    }    }   
 if (mapValue != null) {//如果对应键已经有值了,再把Create方法创建的值回收掉        entryRemoved(false, key, createdValue, mapValue);     
   return mapValue;    } else {
        //控制缓存大小,超出回收最久对象        trimToSize(maxSize);        return createdValue;    }}
 2、put方法
/** * Caches {@code value} for {@code key}. The value is moved to the head of * the queue. * * @return the previous value mapped by {@code key}. */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;}
3、trimToSize
/** * 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. */public void trimToSize(int maxSize) {    while (true) {        K key;        V value;        synchronized (this) {            if (size < 0 || (map.isEmpty() && size != 0)) {                throw new IllegalStateException(getClass().getName()                        + ".sizeOf() is reporting inconsistent results!");            }            if (size <= maxSize) {                break;            }            Map.Entry<K, V> toEvict = map.eldest();            if (toEvict == null) {                break;            }            key = toEvict.getKey();            value = toEvict.getValue();            map.remove(key);            size -= safeSizeOf(key, value);            evictionCount++;        }        entryRemoved(true, key, value, null);    }}



0 0
原创粉丝点击