Android LruCache源码分析

2024-02-23 18:44
文章标签 分析 android 源码 lrucache

本文主要是介绍Android LruCache源码分析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • Android LruCache源码分析
    • 概述
    • LruCache和LinkedHashMap关系
    • 源码分析
      • 属性
      • 写入数据
      • 读取数据
      • 删除缓存

Android LruCache源码分析

概述

LruCache(Least Recently Used Cache,最近最少使用缓存)是 Android 中的一种缓存机制。

根据数据的使用频率淘汰减少使用的数据,当需要缓存新数据时,如果缓存已满,LruCache 会淘汰最近最少使用的数据,腾出空间给新数据。

img

LruCache和LinkedHashMap关系

LruCache 内部使用的是 LinkedHashMap(链式哈希表),这是因为 LinkedHashMap 的构造函数里有个布尔参数 accessOrder,当它为 true 时,LinkedHashMap 会以访问顺序的方式排列元素,如下:

Map<Integer, Integer> map = new LinkedHashMap<>(5, 0.75F, true);
map.put(1, 1);
map.put(2, 2);
map.put(3, 3);
map.put(4, 4);
map.put(5, 5);
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {System.out.println(entry.getValue());
}/** 1* 2* 3* 4* 5*/
// 访问2个元素
map.get(3); 
map.get(4);
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {System.out.println(entry.getValue());
}/** 1* 2* 5* 3* 4*/

最近访问的2个元素被移动到尾部,LruCache 也是从尾部访问数据,在表头删除数据。

源码分析

属性

public class LruCache<K, V> {private final LinkedHashMap<K, V> map;   // 当前缓存大小private int size;// 最大缓存容量private int maxSize;// 写入计数private int putCount;// 创建计数private int createCount;// 淘汰计数private int evictionCount;// 缓存命中计数private int hitCount;// 缓存未命计数private int missCount;
}

写入数据

public final V put(K key, V value) {// 如果值为null,则抛出异常if (key == null || value == null) {throw new NullPointerException("key == null || value == null");}V previous;// 加锁,线程安全synchronized (this) {// 写入计数putCount++;// 通过sizeOf()计算当前项的大小,并累加已有缓存大小size += safeSizeOf(key, value);// 写入操作previous = map.put(key, value);// 如果previous为null表示为新增数据,如果previous不为null表示为修改数据if (previous != null) {// 修改数据需要将size恢复到以前的大小size -= safeSizeOf(key, previous);}}// 回调entryRemoved()方法if (previous != null) {entryRemoved(false, key, previous, value);}// 调整缓存大小trimToSize(maxSize);return previous;
}// 调整缓存大小
public void trimToSize(int maxSize) {// 死循环while (true) {K key;V value;synchronized (this) {// 缓存未满,直接返回if (size <= maxSize || map.isEmpty()) {break;}// 缓存已满情况// 从表头遍历,获取元素Map.Entry<K, V> toEvict = map.entrySet().iterator().next();key = toEvict.getKey();value = toEvict.getValue();// 删除元素map.remove(key);// 减少删除元素的缓存size -= safeSizeOf(key, value);// 删除计数evictionCount++;}// 回调entryRemoved()方法entryRemoved(true, key, value, null);}
}
  • 插入元素,并增加已缓存的大小。
  • 调用 trimToSize() 方法,调整缓存大小。

读取数据

public final V get(@NonNull K key) {if (key == null) {throw new NullPointerException("key == null");}V mapValue;synchronized (this) {// 获取元素,LinkedHashMap会将这个元素移动到表尾mapValue = map.get(key);if (mapValue != null) {hitCount++;return mapValue;}missCount++;}// 没有元素时,会回调create()方法V createdValue = create(key);if (createdValue == null) {return null;}// 下面和put()流程相同synchronized (this) {createCount++;mapValue = map.put(key, createdValue);if (mapValue != null) {map.put(key, mapValue);} else {size += safeSizeOf(key, createdValue);}}if (mapValue != null) {entryRemoved(false, key, createdValue, mapValue);return mapValue;} else {trimToSize(maxSize);return createdValue;}
}
  • 最终调用 LinkedHashMap#get() 方法,因为accessOrder为true ,因此元素会移动到表尾。
  • 如果没有获取到元素时,会调用 create() 方法创建元素,接着执行put()流程。

删除缓存

public final V remove(@NonNull K key) {if (key == null) {throw new NullPointerException("key == null");}V previous;synchronized (this) {// 调用LinkedHashMap#remove()方法删除元素previous = map.remove(key);if (previous != null) {size -= safeSizeOf(key, previous);}}if (previous != null) {entryRemoved(false, key, previous, null);}return previous;
}
  • 调用 LinkedHashMap#remove() 方法删除元素。

这篇关于Android LruCache源码分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/739578

相关文章

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

Android平台播放RTSP流的几种方案探究(VLC VS ExoPlayer VS SmartPlayer)

技术背景 好多开发者需要遴选Android平台RTSP直播播放器的时候,不知道如何选的好,本文针对常用的方案,做个大概的说明: 1. 使用VLC for Android VLC Media Player(VLC多媒体播放器),最初命名为VideoLAN客户端,是VideoLAN品牌产品,是VideoLAN计划的多媒体播放器。它支持众多音频与视频解码器及文件格式,并支持DVD影音光盘,VCD影

Java ArrayList扩容机制 (源码解读)

结论:初始长度为10,若所需长度小于1.5倍原长度,则按照1.5倍扩容。若不够用则按照所需长度扩容。 一. 明确类内部重要变量含义         1:数组默认长度         2:这是一个共享的空数组实例,用于明确创建长度为0时的ArrayList ,比如通过 new ArrayList<>(0),ArrayList 内部的数组 elementData 会指向这个 EMPTY_EL

如何在Visual Studio中调试.NET源码

今天偶然在看别人代码时,发现在他的代码里使用了Any判断List<T>是否为空。 我一般的做法是先判断是否为null,再判断Count。 看了一下Count的源码如下: 1 [__DynamicallyInvokable]2 public int Count3 {4 [__DynamicallyInvokable]5 get

SWAP作物生长模型安装教程、数据制备、敏感性分析、气候变化影响、R模型敏感性分析与贝叶斯优化、Fortran源代码分析、气候数据降尺度与变化影响分析

查看原文>>>全流程SWAP农业模型数据制备、敏感性分析及气候变化影响实践技术应用 SWAP模型是由荷兰瓦赫宁根大学开发的先进农作物模型,它综合考虑了土壤-水分-大气以及植被间的相互作用;是一种描述作物生长过程的一种机理性作物生长模型。它不但运用Richard方程,使其能够精确的模拟土壤中水分的运动,而且耦合了WOFOST作物模型使作物的生长描述更为科学。 本文让更多的科研人员和农业工作者

MOLE 2.5 分析分子通道和孔隙

软件介绍 生物大分子通道和孔隙在生物学中发挥着重要作用,例如在分子识别和酶底物特异性方面。 我们介绍了一种名为 MOLE 2.5 的高级软件工具,该工具旨在分析分子通道和孔隙。 与其他可用软件工具的基准测试表明,MOLE 2.5 相比更快、更强大、功能更丰富。作为一项新功能,MOLE 2.5 可以估算已识别通道的物理化学性质。 软件下载 https://pan.quark.cn/s/57

工厂ERP管理系统实现源码(JAVA)

工厂进销存管理系统是一个集采购管理、仓库管理、生产管理和销售管理于一体的综合解决方案。该系统旨在帮助企业优化流程、提高效率、降低成本,并实时掌握各环节的运营状况。 在采购管理方面,系统能够处理采购订单、供应商管理和采购入库等流程,确保采购过程的透明和高效。仓库管理方面,实现库存的精准管理,包括入库、出库、盘点等操作,确保库存数据的准确性和实时性。 生产管理模块则涵盖了生产计划制定、物料需求计划、

android-opencv-jni

//------------------start opencv--------------------@Override public void onResume(){ super.onResume(); //通过OpenCV引擎服务加载并初始化OpenCV类库,所谓OpenCV引擎服务即是 //OpenCV_2.4.3.2_Manager_2.4_*.apk程序包,存