Android中的LruCache的原理和使用
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依次做了这么几件事:
- 判空,即不允许key/value为null
- 总容量size增加上计算传入的K-V大小
- 将传入的K-V存入LinkedHashMap
- 如过LinkedHashMap中已存在相同K,总容量size减去替换掉的K-VOld大小
- 通知VOld被替换(子类实现entryRemoved以监听)
- 比较总容量size和最大容量maxSize,若大于maxSize则循环移除LinkedHashMap头结点(即最久未被访问的结点)直至size小于等于maxSize
获取
当调用get方法获取存储内容时,LruCache依次做了这些事:
- 判空
- 从LinkedHashMap中取出与K对应的V值并返回。如果子类未实现create方法以达到当缓存未命中时创建并存入新V的话,返回null,get流程结束。
- 通过create创建VNew,并尝试把VNew存储到LinkedHashMap中,流程类似存储过程,不同之处在于当K冲突时,会舍弃掉新创建的VNew。不要奇怪为什么明明上面通过K取V的时候没取到,这里却会K冲突,因为LruCache为了性能考虑(防止子类自定义的create方法耗时过长影响get方法执行性能),只对从LinkedHashMap中取值的过程做了同步处理,这样在多线程的情况下就可能出现A线程在create的时候,B线程已经将K-VB存入了map。
- 返回上面创建的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的原理和使用的更多相关文章
- Android中图像变换Matrix的原理、代码验证和应用(一)
第一部分 Matrix的数学原理 在Android中,如果你用Matrix进行过图像处理,那么一定知道Matrix这个类.Android中的Matrix是一个3 x 3的矩阵,其内容如下: Matri ...
- Android 中View的工作原理
Android中的View在Android的知识体系中扮演着重要的角色.简单来说,View就是Android在视觉的体现.我们所展现的页面就是Android提供的GUI库中控件的组合.但是当要求不能满 ...
- Android中微信抢红包插件原理解析和开发实现
一.前言 自从去年中微信添加抢红包的功能,微信的电商之旅算是正式开始正式火爆起来.但是作为Android开发者来说,我们在抢红包的同时意识到了很多问题,就是手动去抢红包的速度慢了,当然这些有很多原因导 ...
- Android中图像变换Matrix的原理、代码验证和应用(三)
第三部分 应用 在这一部分,我们会将前面两部分所了解到的内容和Android手势结合起来,利用各种不同的手势对图像进行平移.缩放和旋转,前面两项都是在实践中经常需要用到的功能,后一项据说苹果也是最近才 ...
- Android中SensorManager.getRotationMatrix函数原理解释
SensorManager是Android中的一个类,其有一个函数getRotationMatrix,可以计算出旋转矩阵,进而通过getOrientation求得设备的方向(航向角.俯仰角.横滚角). ...
- Android中典型的ROOT原理(5)
ROOT的作用 Customization 用户的个人定制,如删除一些预安装,定制开机动画等. 特权操作 所有需要特权操作的基本都是要通过ROOT,这也是ROOT的初衷. ROOT的第一步:寻找漏洞并 ...
- Android中线程间通信原理分析:Looper,MessageQueue,Handler
自问自答的两个问题 在我们去讨论Handler,Looper,MessageQueue的关系之前,我们需要先问两个问题: 1.这一套东西搞出来是为了解决什么问题呢? 2.如果让我们来解决这个问题该怎么 ...
- Android中图像变换Matrix的原理、代码验证和应用(二)
第二部分 代码验证 在第一部分中讲到的各种图像变换的验证代码如下,一共列出了10种情况.如果要验证其中的某一种情况,只需将相应的代码反注释即可.试验中用到的图片: 其尺寸为162 x 251. 每种变 ...
- [转]Android中handler机制的原理
Andriod提供了Handler 和 Looper 来满足线程间的通信.Handler先进先出原则.Looper类用来管理特定线程内对象之间的消息交换(MessageExchange). 1)Loo ...
随机推荐
- 脱壳实践之寻找OEP——两次内存断点法
0x00 前言 对于加壳程序第一件事就是要找到OEP(oringinal Entry point),由于加壳的缘故,当PE文件载入OD或者其他调试软件时进入的的往往是壳程序的入口地址.所以要进行逆 ...
- js返回上一页并刷新思路
在网上找了很多办法,比如window.history.go(-1):window.history.go(0): 试了下根本没用(不知道是不是我哪里写错了),想着在上一个页面写一个关闭页面并刷新的方法, ...
- Spring @Value注解使用${}进行注入(转)
原文:http://my.oschina.net/js99st/blog/632104 spring3中新增的@value注解 http://bijian1013.iteye.com/blog/202 ...
- 数据可视化之powerBI入门 (一)认识PowerBI
来自 https://zhuanlan.zhihu.com/p/64144024 Power BI是什么? Power BI是微软推出的数据分析和可视化工具,我们先来看看微软官方是怎么介绍的: Po ...
- Worktile完成新一轮融资,将发力研发管理赛道
Worktile 宣布完成B+轮融资.本轮融资由亿联凯泰基金领投,老股东斯道资本.宽带资本跟投.该轮融资将用于公司产品技术研发及市场拓展. 作为企业服务行业的佼佼者,Worktile 始终以打造世界级 ...
- js 左右切换 局部刷新
//刷新地方的ID,后面ID前必须加空格 $("#gwc").load(location.href + " #gwc");
- 索引中丢失 IN 或 OUT 参数:: 103,解决办法
索引中丢失 IN 或 OUT 参数:: 103 这个原因是数据库中的字段类型与SQL语句中的类型不匹配造成的,103代表第103个字段参数错误.找到对应参数配置或者SQL中这个参数的类型是否与数据库 ...
- P4554 小明的游戏 (洛谷) 双端队列BFS
最近没有更新博客,全是因为英语,英语太难了QWQ 洛谷春令营的作业我也不会(我是弱鸡),随机跳了2个题,难度不高,还是讲讲吧,学学新算法也好(可以拿来水博客) 第一题就是这个小明的游戏 小明最近喜欢玩 ...
- P.SDA1.DEV - 一个没有服务器的图床
图床特色 P.SDA1.DEV的愿景是为大家提供一个免费.长期稳定外链分享图片的选择. P.SDA1.DEV的主要特点有: 完全建构在Serverless云服务上,致力于提供(墙外)可用性99.9%的 ...
- 【mysql】- 锁篇(下)
InnoDB存储引擎中的锁 表级锁 表级别的S锁.X锁 在对某个表执行SELECT.INSERT.DELETE.UPDATE语句时,InnoDB存储引擎是不会为这个表添加表级别的S锁或者X锁的 表级别 ...