Android-Universal-Image-Loader学习笔记(3)--内存缓存
这些类的继承关系例如以下图所看到的:
如同文件缓存一样,内存缓存涉及的接口也有两个:MemoryCacheAware 和MemoryCache,当中MemoryCache仅仅是简单的继承了MemoryCacheAware并没有声明其它的方法。
MemoryCacheAware接口的方法例如以下:
@Deprecated
public interface MemoryCacheAware<K, V> {/***依据key值把value放入缓存* @return 假设放入缓存成功的话就返回true,反之返回false*/boolean put(K key, V value);/**依据key从缓存中获取数据,没有相关数据则返回null*/V get(K key);/** 依据key从缓存中删除数据*/void remove(K key);/** 返回缓存中全部的key */Collection<K> keys();/** 清空缓存*/void clear();
}
以下具体介绍这些缓存的作用以及实现方式,先从BaseMemoryCache以及其子类開始
BaseMemoryCache:
该类是一个抽象类,提供了一个map,用来缓存Bitmap的弱引用:
private final Map<String, Reference<Bitmap>> softMap = Collections.synchronizedMap(new HashMap<String, Reference<Bitmap>>());
当中softMap的value字段就是保存了Bimmap的引用类型,因为Reference又分为强引用。弱引用,软引用以及虚引用。所以该该类另外还提供了一个抽象方法createReference(Bitmap value)让子类重写,依据不同的要求来返回不同的应用类型。该抽象方法是将Bitmap转换成一个Reference。在调用BaseMemoryCache的put方法时调用。
/**依据value创建一个弱引用对象。该类为抽象类。供子类实现 */protected abstract Reference<Bitmap> createReference(Bitmap value);@Overridepublic boolean put(String key, Bitmap value) {softMap.put(key, createReference(value));return true;}
LimitedMemoryCache:
该类为抽象类。继承了BaseMemoryChache。对缓存进行了两个限制:
1) 限制每个缓存图片的最大值:用sizeLimit来作为标致,对大于sizeLimit大小的bitmap对象。调用父类的put方法保存bitmap的弱引用。
否则在保存弱引用的同一时候,把Bitmap对象的强引用用类型为LinkedList变量hardCache缓存起来,
2) 相同用sizeLimit来限制整个缓存的大小。对是否超出缓存大小的限制在put方法被调用的时候会做推断。假设缓存大小超出限制就从LinkedList中删除相应的bitmap对象,详细的删除策略有该类的抽象方法remoeNext()提供。详细的在子父类中实现(比方有的是删除最大的那个bitMap,以及依据FIFO算法删除等等),这是典型的模板方法模式的应用。详细的模板方法为romoveNext()和getSize()由相应的子类实现。
注意put方法的返回值,当要增加的bitMap的大小超过sizeLimit的就返回false。否则返回true(在子类中调用该put方法。返回true说明对缓存进行了相应的删除操作)
private final List<Bitmap> hardCache = Collections.synchronizedList(new LinkedList<Bitmap>());<span style="color:#0000C0;">//hardCache</span><span style="color:#0000C0;">仅仅是在此类中仅仅是用来对缓存是否超过</span><span style="color:#0000C0;">sizeLimit</span><span style="color:#0000C0;">做推断。</span>//bitMap放入缓存@Overridepublic boolean put(String key, Bitmap value) {boolean putSuccessfully = false;// Try to add value to hard cache//getSize方法为抽象方法,由子类实现int valueSize = getSize(value);int sizeLimit = this.sizeLimit;int curCacheSize = cacheSize.get();//当bitmap的大小小于sizeLimit的大小时if (valueSize < sizeLimit) {//对缓存进行删除操作,使之不超过siezeLimit的限制,。我们while (curCacheSize + valueSize > sizeLimit) {Bitmap removedValue = removeNext();//removeNext()为抽象方法,由不同的子类提供不同的删除策略if (hardCache.remove(removedValue)) {curCacheSize = cacheSize.addAndGet(-getSize(removedValue));}}//放入缓存hardCache.add(value);//设置缓存大小cacheSize.addAndGet(valueSize);putSuccessfully = true;}//获取bitMap的大小protected abstract int getSize(Bitmap value);//模板方法,由对应的子类来实现详细的删除策略protected abstract Bitmap removeNext();
LargesetLimitedMemoryCache:
该类为LimitedMemoryCache的子类,该类的目的是当超出缓存限制大小的时候删除缓存中最大的那个bitmap对象。
该类实现了父类的两个抽象方法:getSize()和removeNext()来获取某个bitmap的大小和删除最大的那个bitMap对象。
实现的原理: 该类加入了一个map变量,该map的key用来保存bitMap对象,而相应的value则保存bitmap的大小。
private final Map<Bitmap, Integer> valueSizes = Collections.synchronizedMap(new HashMap<Bitmap, Integer>());
详细的removeNext()实现:
/*** 循环遍历valueSizes,并获取最大的那个bitmap,而且从map中删除之 返回的Bimmap对象交给父类的hardCache删除*/@Overrideprotected Bitmap removeNext() {Integer maxSize = null;Bitmap largestValue = null;Set<Entry<Bitmap, Integer>> entries = valueSizes.entrySet();synchronized (valueSizes) {for (Entry<Bitmap, Integer> entry : entries) {if (largestValue == null) {largestValue = entry.getKey();maxSize = entry.getValue();} else {Integer size = entry.getValue();if (size > maxSize) {maxSize = size;largestValue = entry.getKey();}}}}//运行删除稻作valueSizes.remove(largestValue);return largestValue;}//获取getSize的方法@Overrideprotected int getSize(Bitmap value) {return value.getRowBytes() * value.getHeight();}@Overrideprotected Reference<Bitmap> createReference(Bitmap value) {return new WeakReference<Bitmap>(value);}
删除操作运行时机:调用父类put方法是运行
<span style="font-size:12px;">@Overridepublic boolean put(String key, Bitmap value) {if (super.put(key, value)) {//假设父类的方法为空。说明缓存的大小没有超出限制valueSizes.put(value, getSize(value));return true;} else {//缓存的大小超出限制return false;}}</span>
FIFOLimitedMemoryCache :
LimitedMomroyCache的子类,当当前缓存的大小超出限制的时候,会依据FIFO(先进先出)算法删除响应的bitmap缓存对象。该类用LinkedList来作为FIFO的实现方式,当超出缓存大小的时候,调用removeNext()来从缓存中删除首先增加进来的bitmap对象。对应的方法例如以下:
实现原理:提供了一个LinkedList来保存bitmap对象
private final List<Bitmap> queue = Collections.synchronizedList(new LinkedList<Bitmap>());
详细的removeNext()方法实现:
@Overrideprotected Bitmap removeNext() {return queue.remove(0);}@Overrideprotected Reference<Bitmap> createReference(Bitmap value) {return new WeakReference<Bitmap>(value);}@Overrideprotected int getSize(Bitmap value) {return value.getRowBytes() * value.getHeight();}
删除操作运行时机:调用父类put方法是运行
@Overridepublic boolean put(String key, Bitmap value) {if (super.put(key, value)) {//假设缓存没有超出范围queue.add(value);//把bitmap放入队列return true;} else {//缓存超出范围return false;}}
LRULimitedMemoryCache:
LimitedMemoryCache的子类。近期最久未使用缓存,当缓存大小超过sizeLimit限制的时候。就从缓存中删除近期最久未使用的bitmap缓存对象。
实现原理:提供了一个LinkedHashMap来保存对象,实现LRU的效果
/** Cache providing Least-Recently-Used logic */private final Map<String, Bitmap> lruCache = Collections.synchronizedMap(new LinkedHashMap<String, Bitmap>(INITIAL_CAPACITY, LOAD_FACTOR, true));
详细的removeNext()方法实现:
@Overrideprotected Bitmap removeNext() {return queue.remove(0);}@Overrideprotected Reference<Bitmap> createReference(Bitmap value) {return new WeakReference<Bitmap>(value);}@Overrideprotected int getSize(Bitmap value) {return value.getRowBytes() * value.getHeight();}
删除操作运行时机:调用父类put方法是运行
@Overridepublic boolean put(String key, Bitmap value) {if (super.put(key, value)) {//假设缓存没有超出范围queue.add(value);//把bitmap放入队列return true;} else {//缓存超出范围return false;}}
UsingFreqLimitedMemoryCache:
LimitedMemoryCache的子类,当缓存大小超出sizelimit的时候对最久未使用的bitmap对象进行删除(也就是说对使用次数最少的那个bitmap进行删除操作)
实现原理:提供了一个hashMap。该map的key保存bitmap对象,而value则保存相应bitmap的使用次数
private final Map<Bitmap, Integer> usingCounts = Collections.synchronizedMap(new HashMap<Bitmap, Integer>());
当调用get(string key)方法获取bitmap的时候,该bitmap的使用次数进行+1操作
@Overridepublic Bitmap get(String key) {Bitmap value = super.get(key);// Increment usage count for value if value is contained in hardCaheif (value != null) {Integer usageCount = usingCounts.get(value);if (usageCount != null) {//使用次数+1usingCounts.put(value, usageCount + 1);}}return value;}
详细的removeNext()实现方法:
@Overrideprotected int getSize(Bitmap value) {return value.getRowBytes() * value.getHeight();}@Overrideprotected Bitmap removeNext() {Integer minUsageCount = null;Bitmap leastUsedValue = null;Set<Entry<Bitmap, Integer>> entries = usingCounts.entrySet();synchronized (usingCounts) {for (Entry<Bitmap, Integer> entry : entries) {if (leastUsedValue == null) {leastUsedValue = entry.getKey();minUsageCount = entry.getValue();} else {Integer lastValueUsage = entry.getValue();if (lastValueUsage < minUsageCount) {minUsageCount = lastValueUsage;leastUsedValue = entry.getKey();}}}}usingCounts.remove(leastUsedValue);return leastUsedValue;}@Overrideprotected Reference<Bitmap> createReference(Bitmap value) {return new WeakReference<Bitmap>(value);}
删除操作运行时机:调用父类put方法是运行
@Overridepublic boolean put(String key, Bitmap value) {if (super.put(key, value)) {usingCounts.put(value, 0);return true;} else {return false;}}
LimitedAgeMemoryCache:
对超出时间限制的缓存对象进行删除,该类的实现毕竟简单。详细代码例如以下:
public class LimitedAgeMemoryCache implements MemoryCache {private final MemoryCache cache;private final long maxAge;private final Map<String, Long> loadingDates = Collections.synchronizedMap(new HashMap<String, Long>());/*** @param cache Wrapped memory cache* @param maxAge Max object age <b>(in seconds)</b>. If object age will exceed this value then it'll be removed from* cache on next treatment (and therefore be reloaded).*/public LimitedAgeMemoryCache(MemoryCache cache, long maxAge) {this.cache = cache;this.maxAge = maxAge * 1000; // to milliseconds}@Overridepublic boolean put(String key, Bitmap value) {boolean putSuccesfully = cache.put(key, value);if (putSuccesfully) {loadingDates.put(key, System.currentTimeMillis());}return putSuccesfully;}@Overridepublic Bitmap get(String key) {Long loadingDate = loadingDates.get(key);//推断是否超时if (loadingDate != null && System.currentTimeMillis() - loadingDate > maxAge) {cache.remove(key);loadingDates.remove(key);}return cache.get(key);}@Overridepublic void remove(String key) {cache.remove(key);loadingDates.remove(key);}@Overridepublic Collection<String> keys() {return cache.keys();}@Overridepublic void clear() {cache.clear();loadingDates.clear();}
}
FuzzyKeyMemoryCache:
该缓存的作用就是假设缓存中的有一个key和要增加的keytemp相等。就从缓存中删除该key指向的bitmap对象,然后把新的key对象增加到缓存中去。
详细的逻辑例如以下:
@Overridepublic boolean put(String key, Bitmap value) {// Search equal key and remove this entrysynchronized (cache) {String keyToRemove = null;for (String cacheKey : cache.keys()) {//推断缓存中相应的key是否存在,存在就删除if (keyComparator.compare(key, cacheKey) == 0) {keyToRemove = cacheKey;break;}}if (keyToRemove != null) {cache.remove(keyToRemove);}}return cache.put(key, value);}
LruMemoryCache:
又一个近期最久未使用缓存,在这里就不多说了,直接贴代码:
@Overridepublic final boolean put(String key, Bitmap value) { synchronized (this) {size += sizeOf(key, value);Bitmap previous = map.put(key, value);if (previous != null) {size -= sizeOf(key, previous);}}//缓存瘦身,把近期最久未使用的bitMap删除trimToSize(maxSize);return true;}private void trimToSize(int maxSize) {while (true) {String key;Bitmap value;synchronized (this) {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);}}}
转载于:https://www.cnblogs.com/cxchanpin/p/7070803.html
Android-Universal-Image-Loader学习笔记(3)--内存缓存相关推荐
- android universal image loader 缓冲原理详解
1. 功能介绍 1.1 Android Universal Image Loader Android Universal Image Loader 是一个强大的.可高度定制的图片缓存,本文简称为UIL ...
- Redis运维和开发学习笔记(7) 内存管理和过期策略
Redis运维和开发学习笔记(7) 内存管理和过期策略 文章目录 Redis运维和开发学习笔记(7) 内存管理和过期策略 内存回收策略 惰性删除 定时任务删除 maxmemory 过期策略allkey ...
- 【JVM学习笔记】内存回收与内存回收算法 就哪些地方需要回收、什么时候回收、如何回收三个问题进行分析和说明
目录 一.相关名词解释 垃圾收集常用名词 二.哪些地方需要回收 本地方法栈.虚拟机栈.程序计数器 方法区 Java堆 三.什么时候回收 1. 内存能否被回收 内存中的引用类型 引用计数算法 可达性分析 ...
- Android(java)学习笔记176: 远程服务的应用场景(移动支付案例)
一. 移动支付: 用户需要在移动终端提交账号.密码以及金额等数据 到 远端服务器.然后远端服务器匹配这些信息,进行逻辑判断,进而完成交易,返回交易成功或失败的信息给移动终端.用户提交账号. ...
- Android日常开发 - FlexboxLayout学习笔记
Android日常开发 - FlexboxLayout学习笔记 Android日常开发使用FlexboxLayout实现流式布局的效果,FlexboxLayout与h5中的flex使用十分相似,都是将 ...
- 深入理解Java虚拟机(第3版)学习笔记——JAVA内存区域(超详细)
深入理解Java虚拟机(第3版)学习笔记--JAVA内存区域(超详细) 运行时数据区域 程序计数器 java虚拟机栈 本地方法栈 java堆 方法区 运行时常量池 直接内存 对象的创建 对象的内存布局 ...
- Android Studio下载搭建学习笔记01
Android Studio下载搭建学习笔记01 下载Android Studio 安装Android Studio 进入安装向导 选择安装组件 选择安装位置 选择文件菜单 等待安装 启动并配置And ...
- 我的Android进阶之旅------gt;Android中编解码学习笔记
编解码学习笔记(一):基本概念 媒体业务是网络的主要业务之间.尤其移动互联网业务的兴起,在运营商和应用开发商中,媒体业务份量极重,其中媒体的编解码服务涉及需求分析.应用开发.释放license收费等等 ...
- [Android]Android P(9) WIFI学习笔记 - HAL (1)
目录 前文回顾 前言 入口 WifiNative 初始化 打开WIFI IWifiChip IWifiCond ISupplicant 前文回顾 WIFI学习笔记 - Framework (1) WI ...
- Android的LMK机制学习笔记
初识Android的LMK机制 一.文章背景 1.1 LMK中kill进程的关键log(原生系统):![LMK中kill进程的关键log](https://img-blog.csdnimg.cn/78 ...
最新文章
- lwip可以用于发udp_LWIPUDP一对多
- Vue 中多个元素、组件的过渡,及列表过渡
- qt同时连接oracle和mysql_QT连接Oracle和Mysql的详细步骤,已成功~!
- 诗与远方:无题(八十五)- 无字天书
- Hibernate学习笔记--映射配置文件详解
- XSS-Game level 5
- paip.php and or 语句用法作用
- 为什么年龄大了近视还增加_都是做近视手术,为什么价格区别这么大?
- 教你Java 代码性能优化小妙招,速速来看
- JAVA ME游戏----个人移植:9688雷霆战机
- altium designer2020安装教程
- Pyinstaller打包成使用了pyonnet包的exe时报错System.IO.FileNotFoundException:Unable to find assembly ‘XXX.dll‘。
- 推荐 5 个精选公众号
- Python语法基础 三
- 全排列(从大到小排列)
- 相机响应曲线、ISO详解
- Go设置一个工作区打开多个项目
- Matlab中meshgrid的用法
- 功率放大器设计方案(包含原理图+PCB+BOM表)
- .pvr.ccz 与 png 格式 互转的解决方案
热门文章
- python编程狮题库答案_Python编程狮-零基础学Python dans l’App Store
- python 查找算法_python快速查找算法应用实例
- python 40位的数减个位数_Python——进制表示与转换
- php的变量都放在哪里,php变量一般放在哪个位置
- 【Makefile】
- 乐惠科技php面试题,程序员中的奇葩,使用php构建魔兽世界
- C vector详解
- oracle plsql异常,【Oracle篇】异常处理和PLSQL
- 获取客户端ip_代理IP工具能否解决反爬?
- css 竖行进度图_前端学习--汇集了大量 CSS 的使用和学习的示例代码