android缓存Lrucahe

本文深入解析了Android中的LruCache类,介绍了其内部结构及核心方法实现,包括get、put和trimToSize方法的工作原理,并提供了如何重写关键方法以适应特定需求的指导。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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);
    }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值