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的缓存类构建自己的缓存!


本文转自农夫山泉别墅博客园博客,原文链接:http://www.cnblogs.com/yaowen/p/6358199.html,如需转载请自行联系原作者

相关文章
|
C# 开发工具 IDE
Silverlight 控件开发之 "extern alias” 关键字
早在.net2.0, 微软就发布了"extern alias" C#关键字,目的就是为了解决在参照不同的Assembly时类型全名相同的问题。   以前还没觉得有多大的用处,但在做Silverlight DesignTime开发时,深刻感觉到它的必要了。
709 0
|
6天前
|
人工智能 运维 安全
|
4天前
|
人工智能 异构计算
敬请锁定《C位面对面》,洞察通用计算如何在AI时代持续赋能企业创新,助力业务发展!
敬请锁定《C位面对面》,洞察通用计算如何在AI时代持续赋能企业创新,助力业务发展!
|
5天前
|
机器学习/深度学习 人工智能 自然语言处理
B站开源IndexTTS2,用极致表现力颠覆听觉体验
在语音合成技术不断演进的背景下,早期版本的IndexTTS虽然在多场景应用中展现出良好的表现,但在情感表达的细腻度与时长控制的精准性方面仍存在提升空间。为了解决这些问题,并进一步推动零样本语音合成在实际场景中的落地能力,B站语音团队对模型架构与训练策略进行了深度优化,推出了全新一代语音合成模型——IndexTTS2 。
558 17
|
11天前
|
人工智能 JavaScript 测试技术
Qwen3-Coder入门教程|10分钟搞定安装配置
Qwen3-Coder 挑战赛简介:无论你是编程小白还是办公达人,都能通过本教程快速上手 Qwen-Code CLI,利用 AI 轻松实现代码编写、文档处理等任务。内容涵盖 API 配置、CLI 安装及多种实用案例,助你提升效率,体验智能编码的乐趣。
909 109
|
5天前
|
人工智能 测试技术 API
智能体(AI Agent)搭建全攻略:从概念到实践的终极指南
在人工智能浪潮中,智能体(AI Agent)正成为变革性技术。它们具备自主决策、环境感知、任务执行等能力,广泛应用于日常任务与商业流程。本文详解智能体概念、架构及七步搭建指南,助你打造专属智能体,迎接智能自动化新时代。