首先在Android的三级缓存中,其中主要的就是内存缓存和硬盘缓存。这两种缓存机制的实现都应用到了LruCache算法,今天我们就从使用到源码解析,来彻底理解Android中的缓存机制。 

      Android中缓存策略主要包含缓存的添加、获取和删除这三类操作。如何添加和获取缓存这个比较好理解,那么为什么还要删除缓存呢?这是因为不管是内存缓存还是硬盘缓存,它们的缓存大小都是有限的。当缓存满了之后,再想其添加缓存,这个时候就需要删除一些旧的缓存并添加新的缓存。

因此LRU(Least Recently Used)缓存算法便应运而生,LRU是近期最少使用的算法,它的核心思想是当缓存满时,会优先淘汰那些近期最少使用的缓存对象。采用LRU算法的缓存有两种:LrhCache和DisLruCache,分别用于实现内存缓存和硬盘缓存,其核心思想都是LRU缓存算法。

      LruCache是Android 3.1所提供的一个缓存类,所以在Android中可以直接使用LruCache实现内存缓存。而DisLruCache目前在Android 还不是Android SDK的一部分,但是Android官方文档推荐使用该算法来实现硬盘缓存。 

    LruCache是个泛型类,主要算法原理是把最近使用的对象用强引用(即我们平常使用的对象引用方式)存储在 LinkedHashMap 中。当缓存满时,把最近最少使用的对象从内存中移除,并提供了get和put方法来完成缓存的获取和添加操作。


Lrucahce的使用

1 .设置LruCache缓存的大小,一般为当前进程可用容量的1/8。
2  重写sizeOf方法,计算出要缓存的每张图片的大小。

请注意:缓存的总容量和每个缓存对象的大小所用单位要一致。

LruCache的核心思想很好理解,就是要维护一个缓存对象列表,其中对象列表的排列方式是按照访问顺序实现的,即一直没访问的对象,将放在队尾,即将被淘汰。而最近访问的对象将放在队头,最后被淘汰。

Android 的缓存机制 Lrucache_第1张图片

 这个队列是由LinkedHashMap来维护。

而LinkedHashMap是由数组+双向链表的数据结构来实现的。其中双向链表的结构可以实现访问顺序和插入顺序,使得LinkedHashMap中的对按照一定顺序排列起来。

通过下面构造函数来指定LinkedHashMap中双向链表的结构是访问顺序还是插入顺序。

public LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder) {    super(initialCapacity, loadFactor);    this.accessOrder = accessOrder; }
当accessOrder设置为true则为访问顺序,为false,则为插入顺序。

put()方法 public final V put(K key, V value) {   //不可为空,否则抛出异常 if (key == null || value == null) {    throw new NullPointerException( "key == null || value == null");  }  V previous; synchronized ( this) {   //插入的缓存对象值加1   putCount++;   //增加已有缓存的大小   size += safeSizeOf(key, value);    //向map中加入缓存对象   previous = map.put(key, value);   //如果已有缓存对象,则缓存大小恢复到之前 if (previous != null) { size -= safeSizeOf(key, previous); } }   //entryRemoved()是个空方法,可以自行实现 if (previous != null) {  entryRemoved( false, key, previous, value); }    //调整缓存大小(调用的重点) trimToSize(maxSize);   return previous; } 调用 trimToSize()方法,来判断缓存是否已满,如果满了就要删除近期最少使用的算法。
public void trimToSize(int maxSize) {    //死循环    while ( true) {   K key;  V value;   synchronized ( this) {    //如果map为空并且缓存size不等于0或者缓存size小于0,抛出异常    if (size < 0 || ( map.isEmpty() && size != 0)) {    throw new IllegalStateException(getClass().getName() + ".sizeOf() is reporting inconsistent results!");   }    //如果缓存大小size小于最大缓存,或者map为空,不需要再删除缓存对象,跳出循环 if (size <= maxSize || map.isEmpty()) {   break;   }    //迭代器获取第一个对象,即队尾的元素,近期最少访问的元素   Map.Entry toEvict = map.entrySet().iterator().next();  key = toEvict.getKey();  value = toEvict.getValue();   //删除该对象,并更新缓存大小    map.remove(key);  size -= safeSizeOf(key, value);   evictionCount++;   }  entryRemoved( true, key, value, null);   }   }
 


 


 

 

更多相关文章

  1. 【Android 内存优化】Bitmap 内存缓存 ( Bitmap 缓存策略 | LruC
  2. Android Market排名算法及规则
  3. Android绘制文本对象FontMetrics介绍及繪製文本
  4. android context.getCacheDir()缓存目录
  5. Android异步加载图像小结 (含线程池,缓存方法)
  6. Android 中的 Looper 对象
  7. 关于Android/java的复杂对象的深拷贝和浅拷贝
  8. 【Android 内存优化】Bitmap 内存缓存 ( Bitmap 内存复用 | 弱引
  9. android 使用Intent传递对象 Serializable 或者 Parcelabel 《第

随机推荐

  1. Android 之 Eclipse 导入 Android 源码
  2. TextView过长显示省略号, TextView文字中
  3. android:textAppearance解析
  4. Android异步处理三:Handler+Looper+Messag
  5. android setGravity()的使用
  6. Android CTS的使用
  7. Android中的Selector的用法
  8. Android检查权限
  9. EditText属性及使用
  10. Android体系结构