Image-Loader LruMemoryCache
这段时间在研究Universal-Image-Loader 这个图片处理开源框架,这里主要分析一下它的LRU(Least Resently Used,最近最少使用算法)内存缓存的实现。
在UIL它提供的默认缓存类是LruMemoryCache,在它类上面有如下一段注释:
/**
* A cache that holds strong references to a limited number of Bitmaps. Each time a Bitmap is accessed, it is moved to
* the head of a queue. When a Bitmap is added to a full cache, the Bitmap at the end of that queue is evicted and may become eligible for garbage collection.<br />
* <b>NOTE:</b> This cache uses only strong references for stored Bitmaps.
*/
说明该缓存存储的是强引用的Bitmap对象,同时每当一个bitmap被访问之后,它就会被放到队列的头部,当队列满了需要删除元素时,就会删除队尾的元素,让它变成可以被垃圾回收器回收的对象。
在LruMemoryCache中声明了三个全局变量:
private final LinkedHashMap<String, Bitmap> map;//存放对象的map容器
private final int maxSize; //缓存设定的最大值
/** Size of this cache in bytes */
private int size; //缓存中已经占有的大小
它的构造数也同样简单:
public LruMemoryCache(int maxSize) {
if (maxSize <= 0) {
throw new IllegalArgumentException("maxSize <= 0");
}
this.maxSize = maxSize;
this.map = new LinkedHashMap<String, Bitmap>(0, 0.75f, true);
}
这里传进来的maxSize参数在默认的情况下是程序进程占用内存总数的八分之一,单位是Byte。
根据Key值获取对应的bitmap对象,代码超简单:
/**
* Returns the Bitmap for {@code key} if it exists in the cache. If a Bitmap was returned, it is moved to the head
* of the queue. This returns null if a Bitmap is not cached.
*/
@Override
public final Bitmap get(String key) {
if (key == null) {
throw new NullPointerException("key == null");
}
synchronized (this) {
return map.get(key);
}
}
存储bitmap对象:
@Override
public final boolean put(String key, Bitmap value) {
if (key == null || value == null) {
throw new NullPointerException("key == null || value == null");
}
synchronized (this) {
size += sizeOf(key, value); //调用sizeOf这个函数获得该bitmap对象的占用内存的大小,并且让缓存总数增加
Bitmap previous = map.put(key, value);//这里就是把对象放入容器中的最核心的一句代码,如果容器中已经有了此元素,则返回该元素的value值,否则返回空
if (previous != null) {
size -= sizeOf(key, previous);//如果容器中已经有了此元素,则需要把增加的数量减掉
}
}
trimToSize(maxSize); //此函数计算是否超出最大限量,是则删除队尾元素
return true;
}
这里涉及到两个函数:
获取图片大小的函数
private int sizeOf(String key, Bitmap value) {
return value.getRowBytes() * value.getHeight();
}
保证缓存内存量不超过设定的最大值
private void trimToSize(int maxSize) {
while (true) {
String key;
Bitmap value;
synchronized (this) {
if (size < 0 || (map.isEmpty() && size != 0)) {
throw new IllegalStateException(getClass().getName() + ".sizeOf() is reporting inconsistent results!");
}
if (size <= maxSize || map.isEmpty()) {
break;
}
Map.Entry<String, Bitmap> toEvict = map.entrySet().iterator().next();
if (toEvict == null) {
break;
}
key = toEvict.getKey();
value = toEvict.getValue();
map.remove(key);
size -= sizeOf(key, value);
}
}
}
此外,该类还有一个移除特定key的元素的方法:
/** Removes the entry for {@code key} if it exists. */
@Override
public final Bitmap remove(String key) {
if (key == null) {
throw new NullPointerException("key == null");
}
synchronized (this) {
Bitmap previous = map.remove(key);
if (previous != null) {
size -= sizeOf(key, previous);
}
return previous;
}
}
至此整个缓存类就已经解析完了,你会发现其实代码超简单的,其中一个最重要的东西就是存放键值对的容器–LinkedHashMap。LinkedHashMap实现了Map接口,并且具有链表的特性,即有可预知的迭代顺序。通常在默认的情况下,该集合的迭代顺序是按照插入元素的顺序,先插入的元素在队尾,最后插入的在头部;然而当我们调用LinkedHashMap的构造函数LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder) ,并传入accessOrder的值为true时,LinkedHashMap就会按照访问先后的顺序迭代,最近被访问的放在队头,最迟访问的在队尾。正是因为这个特性,LinkedHashMap很适合被用来作为LRU缓存的容器。因此有了LinkedHashMap这个神器,我们完全可以仿照UIL的缓存类构建自己的缓存!
Image-Loader LruMemoryCache的更多相关文章
- universal image loader自己使用的一些感受
1.全局入口的Application定义初始化: ImageLoaderConfiguration configuration = new ImageLoaderConfiguration.Build ...
- Android中Universal Image Loader开源框架的简单使用
UIL (Universal Image Loader)aims to provide a powerful, flexible and highly customizable instrument ...
- universal image loader在listview/gridview中滚动时重复加载图片的问题及解决方法
在listview/gridview中使用UIL来display每个item的图片,当图片数量较多需要滑动滚动时会出现卡顿,而且加载过的图片再次上翻后依然会重复加载(显示设置好的加载中图片) 最近在使 ...
- 【Android应用开发】 Universal Image Loader ( 使用简介 | 示例代码解析 )
作者 : 韩曙亮 转载请注明出处 : http://blog.csdn.net/shulianghan/article/details/50824912 相关地址介绍 : -- Universal I ...
- android universal image loader 缓冲原理详解
1. 功能介绍 1.1 Android Universal Image Loader Android Universal Image Loader 是一个强大的.可高度定制的图片缓存,本文简称为UIL ...
- webpack入门教程之初识loader(二)
上一节我们学习了webpack的安装和编译,这一节我们来一起学习webpack的加载器和配置文件. 要想让网页看起来绚丽多彩,那么css就是必不可少的一份子.如果想要在应用中增加一个css文件,那么w ...
- 简单实用的进度条加载组件loader.js
本文提供一个简单的方法实现一个流程的进度条加载效果,以便在页面中可以通过它来更好地反馈耗时任务的完成进度.要实现这个功能,首先要考虑怎样实现一个静态的进度条效果,类似下面这样的: 这个倒是比较简单,两 ...
- 怎样写一个webpack loader
div{display:table-cell;vertical-align:middle}#crayon-theme-info .content *{float:left}#crayon-theme- ...
- 异常:java.lang.LinkageError: loader constraint violation: when resolving interface method
异常:java.lang.LinkageError: loader constraint violation: when resolving interface method "javax. ...
- ClassNotFoundException: org.apache.catalina.loader.DevLoader 自己摸索,丰衣足食
使用tomcat插件时遇到的问题: ClassNotFoundException: org.apache.catalina.loader.DevLoader 解决方案: 参考了许多文章,对我自己的目录 ...
随机推荐
- 怎么去除innerHTML获得内容中的标签?
去掉innerHTML获得内容里面的标签: <body> <div id="d1"><p id="p1">hello wor ...
- WLAN STA/AP 并发
WLAN STA/AP 并发 Android 9 引入了可让设备同时在 STA 和 AP 模式下运行的功能.对于支持双频并发 (DBS) 的设备,此功能让一些新功能得以实现,例如在用户想要启用热点 ( ...
- webpack(零工程构建一个前端项目)详解
工作流程记录: 1.初始化项目:npm init -y 2.安装webpack,vue,vue-loader npm install webpack vue vue-loader 3.按装之后根据警告 ...
- bzoj1615 麻烦的干草打包机 BFS
Description Farmer John新买的干草打包机的内部结构大概算世界上最混乱的了,它不象普通的机器一样有明确的内部传动装置,而是,N (2 <= N <= 1050)个齿轮互 ...
- 包及常用模块(time、datetime、random、sys)
什么是包?‘ #官网解释 Packages are a way of structuring Python’s module namespace by using “dotted module nam ...
- [NOIP2009提高组]最优贸易
题目:洛谷P1073.Vijos P1754.codevs1173. 题目大意:有n点m边的图,边分有向和无向.每个点有一个价格,用这个价格可以买入或卖出一个东西.一个人从1出发,要到n,途中可以买入 ...
- [NOIP2013提高组]货车运输
题目:洛谷P1967.Vijos P1843.codevs3287. 题目大意:有n个城市m条道路,每条道路有一个限重,规定货车运货不能超过限重.有一些询问,问你两个城市之间一次最多能运多少重的货(可 ...
- zabbix 使用自带模板监控mysql
1.这里可以采用zabbix自带的mysql模版,但是也需要在mysql服务器上准备获取mysql status的脚本chk_mysql.sh,zabbix通过调用这个脚本来获取mysql的运行信息. ...
- 首家5G体验厅在深圳建成
日前,深圳移动卓越时代营业厅推出5G全方位体验活动,让市民亲身感受5G时代到来.据悉,十大5G展示项目生动展现移动5G带来的生活巨变与产业升级,为5G发展汇聚各界力量加速创新落地. 现场有市民表示,5 ...
- Windows 10 计划带来颜文字和Sandbox
在最新的 Window 10 测试版 Build 18305 中,Windows 10 增加了对颜文字(kaomoji)的支持. Kaomoji 是由日本符号序列组成的面脸部表情的名称.虽然有些人,比 ...