Android 的缓存机制 Lrucache
首先在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的核心思想很好理解,就是要维护一个缓存对象列表,其中对象列表的排列方式是按照访问顺序实现的,即一直没访问的对象,将放在队尾,即将被淘汰。而最近访问的对象将放在队头,最后被淘汰。
这个队列是由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
更多相关文章
- 【Android 内存优化】Bitmap 内存缓存 ( Bitmap 缓存策略 | LruC
- Android Market排名算法及规则
- Android绘制文本对象FontMetrics介绍及繪製文本
- android context.getCacheDir()缓存目录
- Android异步加载图像小结 (含线程池,缓存方法)
- Android 中的 Looper 对象
- 关于Android/java的复杂对象的深拷贝和浅拷贝
- 【Android 内存优化】Bitmap 内存缓存 ( Bitmap 内存复用 | 弱引
- android 使用Intent传递对象 Serializable 或者 Parcelabel 《第