频道栏目
首页 > 资讯 > Android > 正文

Android 的缓存机制 Lrucache

18-06-08        来源:[db:作者]  
收藏   我要投稿

首先在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) {//插入的缓存对象值加1putCount++;//增加已有缓存的大小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);}}。

相关TAG标签
上一篇:jsp用代码将CST格式的时间转换为GTM格式的时间
下一篇:jQuery Validate 插件 验证基本使用方法及注意事项详解(代码实例)
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站