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. python中获取文件路径的几种方式

    # 如果执行文件为E:\aa\bb\aa.py 1.获取当前路径 current_path11 = os.path.abspath(__file__) current_path12 = os.path ...

  2. Deno 学习笔记(1)安装及简单的request

    Deno下载和安装 PowerShell iwr https://deno.land/x/install/install.ps1 -useb | iex Shell curl -fsSL https: ...

  3. scrapy(四): 爬取二级页面的内容

    scrapy爬取二级页面的内容 1.定义数据结构item.py文件 # -*- coding: utf-8 -*- ''' field: item.py ''' # Define here the m ...

  4. python数据处理(六)之数据清洗:标准化和脚本化

    1.数据归一化和标准化 a. 归一化:对数据集进行计算,使数据都位于一个特定的范围\ b.标准化: c.删除离群值 2.数据存储 a.保存到SQLite数据库中 b.导出到简单的文件中csv 3.找到 ...

  5. 数据可视化之PowerQuery篇(一)空值(null)运算的的解决思路

    https://zhuanlan.zhihu.com/p/81535007 星友们在知识星球(PowerBI星球)提出的问题中,关于空值的运算经常被提及.平时接触到的源数据常常有空值,比如Excel数 ...

  6. 前端02 /HTML标签

    前端02 /HTML标签 目录 前端02 /HTML标签 1.特殊字符 2.标签分类 标签嵌套 1.块级标签(行内标签) 1.1div标签(块标签) 1.2p标签(块标签) 2.内联标签 2.1 sp ...

  7. 深入浅出AQS源码解析

    最近一直在研究AQS的源码,希望可以更深刻的理解AQS的实现原理.虽然网上有很多关于AQS的源码分析,但是看完以后感觉还是一知半解.于是,我将自己的整个理解过程记录下来了,希望对大家有所帮助. 基本原 ...

  8. 基于.NetCore3.1系列 ——认证授权方案之Swagger加锁

    一.前言 在之前的使用Swagger做Api文档中,我们已经使用Swagger进行开发接口文档,以及更加方便的使用.这一转换,让更多的接口可以以通俗易懂的方式展现给开发人员.而在后续的内容中,为了对a ...

  9. Python Ethical Hacking - VULNERABILITY SCANNER(7)

    VULNERABILITY_SCANNER How to discover a vulnerability in a web application? 1. Go into every possibl ...

  10. Dresdon简介

    很久没有写文章了.这几年经历了很多事情:离开VMware的不舍,拿到融资的开心,重回VMware的亲切,以及不再争强好胜,只做自己喜欢事情的平和. 可以说,我是幸运的:我这一辈子都在选择,而不是被迫接 ...