Android中的LruCache的原理和使用

LruCache,虽然很多文章都把LRU翻译成“最近最少使用”缓存策略,但Android中的LruCache真的如此吗?

答案是No,它只做到了控制“最近使用”!

原理

数据结构

LruCache采用LinkedHashMap作为存储的数据结构,那么为什么是LinkedHashMap?

LinkedHashMap特性简介

  • LinkedHashMap基于HashMap,具有HashMap高效查找、自动扩容等特性
  • 在HashMap基础上,增加了一个双向链表存储K-V对、实现了自己的遍历器LinkedHashIterator,默认情况下可以做到根据数据插入顺序有序地遍历
  • 提供重载构造方法供外部控制accessOrder,以实现根据访问顺序有序地遍历

初始化

    public LruCache(int maxSize) {
if (maxSize <= 0) {
throw new IllegalArgumentException("maxSize <= 0");
}
this.maxSize = maxSize;
this.map = new LinkedHashMap<K, V>(0, 0.75f, true);
}

LruCache的构造方法如上,可见LruCache初始化时就使用了上面提到的LinkedHashMap的第三点特性,即在数据结构层面实现了“最近使用”。

存储

当调用put方法添加/设置存储内容时,LruCache依次做了这么几件事:

  1. 判空,即不允许key/value为null
  2. 总容量size增加上计算传入的K-V大小
  3. 将传入的K-V存入LinkedHashMap
  4. 如过LinkedHashMap中已存在相同K,总容量size减去替换掉的K-VOld大小
  5. 通知VOld被替换(子类实现entryRemoved以监听)
  6. 比较总容量size和最大容量maxSize,若大于maxSize则循环移除LinkedHashMap头结点(即最久未被访问的结点)直至size小于等于maxSize

获取

当调用get方法获取存储内容时,LruCache依次做了这些事:

  1. 判空
  2. 从LinkedHashMap中取出与K对应的V值并返回。如果子类未实现create方法以达到当缓存未命中时创建并存入新V的话,返回null,get流程结束。
  3. 通过create创建VNew,并尝试把VNew存储到LinkedHashMap中,流程类似存储过程,不同之处在于当K冲突时,会舍弃掉新创建的VNew。不要奇怪为什么明明上面通过K取V的时候没取到,这里却会K冲突,因为LruCache为了性能考虑(防止子类自定义的create方法耗时过长影响get方法执行性能),只对从LinkedHashMap中取值的过程做了同步处理,这样在多线程的情况下就可能出现A线程在create的时候,B线程已经将K-VB存入了map。
  4. 返回上面创建的VNew或者VB

使用

用LruCache实现一个简单的图片缓存

    class LruImageCache extends LruCache<String, Bitmap> {
private static final String TAG = "LruImageCache";
private static final int DEFAULT_CACHE_SIZE = 20 * 1024 * 1024; public LruImageCache() {
this(DEFAULT_CACHE_SIZE);
} public LruImageCache(int maxSize) {
super(maxSize);
} @Override
protected void entryRemoved(boolean evicted, String key, Bitmap oldValue, Bitmap newValue) {
Log.d(TAG, "cache removed: " + key);
} @Override
protected Bitmap create(String key) {
// 从本地、网络获取图片
return loadImageFromIO(key);
} @Override
protected int sizeOf(String key, Bitmap value) {
return value.getAllocationByteCount();
}
}
//使用
Bitmap b = LruImageCache.get("http://image-path");

Android中的LruCache的原理和使用的更多相关文章

  1. Android中图像变换Matrix的原理、代码验证和应用(一)

    第一部分 Matrix的数学原理 在Android中,如果你用Matrix进行过图像处理,那么一定知道Matrix这个类.Android中的Matrix是一个3 x 3的矩阵,其内容如下: Matri ...

  2. Android 中View的工作原理

    Android中的View在Android的知识体系中扮演着重要的角色.简单来说,View就是Android在视觉的体现.我们所展现的页面就是Android提供的GUI库中控件的组合.但是当要求不能满 ...

  3. Android中微信抢红包插件原理解析和开发实现

    一.前言 自从去年中微信添加抢红包的功能,微信的电商之旅算是正式开始正式火爆起来.但是作为Android开发者来说,我们在抢红包的同时意识到了很多问题,就是手动去抢红包的速度慢了,当然这些有很多原因导 ...

  4. Android中图像变换Matrix的原理、代码验证和应用(三)

    第三部分 应用 在这一部分,我们会将前面两部分所了解到的内容和Android手势结合起来,利用各种不同的手势对图像进行平移.缩放和旋转,前面两项都是在实践中经常需要用到的功能,后一项据说苹果也是最近才 ...

  5. Android中SensorManager.getRotationMatrix函数原理解释

    SensorManager是Android中的一个类,其有一个函数getRotationMatrix,可以计算出旋转矩阵,进而通过getOrientation求得设备的方向(航向角.俯仰角.横滚角). ...

  6. Android中典型的ROOT原理(5)

    ROOT的作用 Customization 用户的个人定制,如删除一些预安装,定制开机动画等. 特权操作 所有需要特权操作的基本都是要通过ROOT,这也是ROOT的初衷. ROOT的第一步:寻找漏洞并 ...

  7. Android中线程间通信原理分析:Looper,MessageQueue,Handler

    自问自答的两个问题 在我们去讨论Handler,Looper,MessageQueue的关系之前,我们需要先问两个问题: 1.这一套东西搞出来是为了解决什么问题呢? 2.如果让我们来解决这个问题该怎么 ...

  8. Android中图像变换Matrix的原理、代码验证和应用(二)

    第二部分 代码验证 在第一部分中讲到的各种图像变换的验证代码如下,一共列出了10种情况.如果要验证其中的某一种情况,只需将相应的代码反注释即可.试验中用到的图片: 其尺寸为162 x 251. 每种变 ...

  9. [转]Android中handler机制的原理

    Andriod提供了Handler 和 Looper 来满足线程间的通信.Handler先进先出原则.Looper类用来管理特定线程内对象之间的消息交换(MessageExchange). 1)Loo ...

随机推荐

  1. Git超详细用法,通俗易懂

    创建本地仓库 和 远端共享仓库 直接下载安装包:Git下载地址 安装 git,查看 git 版本,git version 配置项目的 git 账号 git config --global user.n ...

  2. 武科WUST-CTF2020“Tiki组 ”

    赛事信息 官网地址:https://ctfgame.w-ais.cn/参赛地址:https://ctfgame.w-ais.cn/起止时间:2020-03-27 18:00:00 - 2020-03- ...

  3. Java 字符串比较、拼接问题

    @ 目录 1.字符串的比较 1. 1 字符串常量池 1.2 String类型的比较方式 1.3 String的创建方式 1.3.1 直接使用"="进行赋值 1.3.2 使用&quo ...

  4. 数据可视化之powerBI入门(九)PowerBI数据建模:其实一点都不高深

    https://zhuanlan.zhihu.com/p/64149834 数据建模并没有那么高深,你同样可以学会!这篇文章通过一个实例创建一个简单的数据建模,并引出两个重要的概念:度量值和DAX. ...

  5. 数据分析07 /matplotlib绘图

    数据分析07 /matplotlib绘图 目录 数据分析07 /matplotlib绘图 1. 绘制线性图:plt.plot() 2. 绘制柱状图:plt.bar() 3. 绘制直方图:plt.his ...

  6. POJ 1050 To the Max 最详细的解题报告

    题目来源:To the Max 题目大意:给定一个N*N的矩阵,求该矩阵中的某一个矩形,该矩形内各元素之和最大,即最大子矩阵问题. 解题方法:最大子序列之和的扩展 解题步骤: 1.定义一个N*N的矩阵 ...

  7. HotSpot的对象模型(5)

    Java对象通过Oop来表示.Oop指的是 Ordinary Object Pointer(普通对象指针).在 Java 创建对象实例的时候创建,用于表示对象的实例信息.也就是说,在 Java 应用程 ...

  8. Jmeter系列(45)- 详解 Jmeter 跨线程组取参数值的方法,免代码!

    如果你想从头学习Jmeter,可以看看这个系列的文章哦 https://www.cnblogs.com/poloyy/category/1746599.html 前言 用过 Jmeter 的同学应该都 ...

  9. bzoj1787[Ahoi2008]Meet 紧急集合&bzoj1832[AHOI2008]聚会

    bzoj1787[Ahoi2008]Meet 紧急集合 bzoj1832[AHOI2008]聚会 题意: 给个树,每次给三个点,求与这三个点距离最小的点. 题解: 倍增求出两两之间的LCA后,比较容易 ...

  10. 没错,用三方 Github 做授权登录就是这么简单!(OAuth2.0实战)

    本文收录在个人博客:www.chengxy-nds.top,技术资源共享. 上一篇<OAuth2.0 的四种授权方式>文末说过,后续要来一波OAuth2.0实战,耽误了几天今儿终于补上了. ...