Android-Universal-Image-Loader学习笔记(3)--内存缓存

前面的两篇博客写了文件缓存。如今说说Android-Universal-Image-Loader的内存缓存。该内存缓存涉及到的类如图所看到的

这些类的继承关系例如以下图所看到的:

如同文件缓存一样,内存缓存涉及的接口也有两个: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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/355329.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

css设置字体颜色怎么设,css里面怎么设置字体颜色?

在html中我们经常要用到css样式来美化html标签的一些不足之处&#xff0c;今天我们就来说说如何用css的基本样式来改变文本的颜色&#xff0c;文章通俗易懂&#xff0c;希望大家看完后能练习练习加深印象。一、首先我们先给大家看个html字体的基础代码&#xff1a;HTML中文网字…

visio科学图形包_科学网—科研必备:几款好用的流程图工具,助力你的论文/科研绘图...

写SCI论文常常会遇到一个问题——如何才能让读者通俗易懂地理解自己的研究&#xff1f;如果不能让读者了解研究过程&#xff0c;读者会对研究结果是否合理、如何应用存在疑问&#xff1b;尤其是期刊编辑和审稿人如果不能通过咱们的叙述&#xff0c;清楚地了解研究内容&#xff…

网络通信基础(草稿)

应用层&#xff1a;httpd/ssh/ 等软件 应用层功能&#xff1a;规定应用程序的数据格式。传输层&#xff1a;tcp/udp --> port&#xff0c;唯一标识一个主机上的某个进程 端口范围0-65535&#xff0c;0-1023为系统占用端口 传输层的功能&#xff1a;建立端口到端口的通信…

JSF范围教程– JSF / CDI会话范围

会话作用域跨越多个HTTP请求-响应周期&#xff08;理论上是无限的&#xff09;。 当您需要每个HTTP请求-响应周期进行一次交互时&#xff0c;请求作用域在任何Web应用程序中都非常有用。 但是&#xff0c;当您需要对属于用户会话的任何HTTP请求-响应周期可见的对象时&#xf…

数字通信原理_光耦继电器在实际应用中的作用以及工作原理!

光耦继电器---先进光半导体由于光耦继电器输入输出间互相隔离&#xff0c;电信号传输具有单向性等特点&#xff0c;因而具有良好的电绝缘能力和抗干扰能力。又由于光耦的输入端属于电流型工作的低阻元件&#xff0c;因而具有很强的共模抑制能力。所以&#xff0c;它在长线传输信…

css的fill属性,css column-fill属性怎么用

css column-gap属性定义及用法在css中&#xff0c;column-gap属性通常和columns、column-count等分列属性一起使用&#xff0c;用来设置元素内容分列(多列布局)后列与列之间的距离css column-gap属性语法格式css语法&#xff1a;column-gap: length / normal;(例&#xff1a;co…

css点击事件不做反应,纯css无js实现点击事件

已经阅读主要根据的技术点&#xff1a;标签为 input 元素定义标注(标记)。label 元素不会向用户呈现任何特殊效果。不过&#xff0c;它为鼠标用户改进了可用性。如果您在 label 元素内点击文本&#xff0c;就会触发此控件。就是说&#xff0c;当用户选择该标签时&#xff0c;浏…

Spring Integration Framework简介

我们非常了解Spring框架和JMS 。 在本文中&#xff0c;我们将介绍称为Spring Integration的企业集成框架 。 Spring Integration是一个开源企业集成框架&#xff0c;可增强Spring单独完成的功能。 Spring Integration构建在Spring的IoC之上&#xff0c;它抽象了消息源和目标&am…

网络营销广告投放策略

网络营销广告投放策略 网络营销第一桶金&#xff1a;10年微博热火&#xff0c;粉丝1毛一个&#xff0c;我看到了这个机会。开发了注册微博账户的软件可以卖粉丝了怎么推广呢微博账户头像上加广告&#xff0c;去关注活人&#xff0c;被关住的人&#xff0c;就能看到广告&#xf…

空间皮肤代码_OpenCV实现皮肤表面粗糙度3D显示

点击上方蓝字关注我们微信公众号&#xff1a;OpenCV学堂关注获取更多计算机视觉与深度学习知识问题分析与思路这个是最近有人问我的一个问题&#xff0c;想把一个拍好的皮肤图像&#xff0c;转换为3D粗糙度表面显示&#xff0c;既然是粗糙度表面显示&#xff0c;我想到的就是把…

windows修改时间服务器,在Windows中设置时间服务器 2012 R2

大家都知道, 时的服务是任何网络中最重要的组成部分, 任何系统, 在所有计算机上同步时钟是我们可以做的事情工作&#xff0c;也都成功同步的内部系统最少. 通常情况下&#xff0c;我们有一个网络时间服务器以从外部时钟获得的时间和内部提供.什么NTP服务器的默认地图, 在这种情…

q版地图制作软件_Flash动画的图形元件实例-Q版人物侧面行走

对于刚入门者而言&#xff0c;学会了基本图形的绘制之后&#xff0c;如何应用软件的各种动画补间功能&#xff0c;制作出具有表现力的动画&#xff0c;就需要更进一阶的知识技能了&#xff1b;那么&#xff0c;设计制作一个卡通人物的行走效果&#xff0c;如何从没有头绪的任务…

绝地服务器维护7月5日,绝地求生正式服7月5日停机更新维护内容公告

我们将在北京时间7月5日(星期四) 上午10点 开始正式服的停机维护。- 维护开始时间&#xff1a;7月5日(星期四) 上午10点 (预计3小时)玩家们大家好&#xff0c;伴随PGI2018的临近&#xff0c;我们将向大家呈现以PGI为主题、全新风格的PUBG。我们将向玩家们提供丰富的活动和奖品&…

javafx2_JavaFX 2 GameTutorial第1部分

javafx2介绍 我相信大多数软件开发人员可能会在年轻人&#xff08;年轻人&#xff09;生活的某一时刻被迫创建游戏来帮助他们学习编程语言&#xff08;我知道我曾经做过&#xff09;。 以前&#xff0c;我的第一台计算机实际上是Franklin Ace 1000 &#xff0c;后来是Apple [] …

webstorm最新破解方法

方法来自 Rover12421 大神。 1.从官网下载WebStorm2016.1安装。 2.下载 破解补丁 并解压&#xff0c;记住路径 3.编辑WebStorm安装目录下 bin 文件夹中的 WebStorm.exe.vmoptions 与 WebStorm64.exe.vmoptions 文件&#xff0c; 在头部加上 -javaagent:D:\Program Files (x86)\…

ajax 页面无刷新,Ajax的页面无刷新实现详解(附代码)

这次给大家带来Ajax的页面无刷新实现详解(附代码)&#xff0c;Ajax页面无刷新实现的注意事项有哪些&#xff0c;下面就是实战案例&#xff0c;一起来看一下。ajax (ajax开发)AJAX即“Asynchronous Javascript And XML”(异步JavaScript和XML)&#xff0c;是指一种创建交互式网页…

运营管理最新版史蒂文森_运营增长人都在看的硬核案例拆解是怎么做的?

你会拆案例吗&#xff1f;大部分运营增长人听到这个问题都会愣一下&#xff0c;心想这有什么会拆不会拆的&#xff1f;看一下活动规则&#xff0c;把流程走一遍&#xff0c;不就可以了&#xff1f;当马上要做活动但又没思路缺灵感时&#xff0c;我们通常会试着先去关注一下相关…

pc网站和移动网站在同一服务器吗,机动都市阿尔法PC服和移动服互通吗

机动都市阿尔法PC服已经开启了&#xff0c;很多小伙伴想知道这个PC服和移动服有什么区别&#xff0c;互通情况怎么样&#xff0c;下面就是机动都市阿尔法PC服和移动服互通的具体内容&#xff0c;一起来看看吧。PC服和移动服互通吗国服PC版开启时&#xff0c;将额外增设一个独立…

teamcity_TeamCity构建依赖项

teamcity介绍 构建依赖关系的主题既非琐碎的&#xff0c;也非次要的。 各种构建工具从不同的角度处理此主题&#xff0c;从而提供了各种解决方案&#xff0c;每种解决方案都有其优点和缺点。 熟悉发行版和快照依赖关系的Maven和Gradle用户可能不了解TeamCity快照依赖关系&…

刷新器-Java EE 7后端十大功能

这是我的Java EE 7小知识系列的第二部分。 在进行简要介绍的第一个介绍之后&#xff0c;我决定请Arjan Tijms撰写有关Java EE 7中他最喜欢的新后端功能的文章。如果您关注Java EE领域&#xff0c;您将知道Arjan。 他是Java EE开发人员&#xff0c;JSF和Security EG的长期成员&a…