当前位置: 首页 > news >正文

RecyclerView详解——(四)缓存复用机制

稍微看了下源码和部分文章,在此做个小小的总结

RecyclerView,意思为可回收的view,那么相对于listview,他的缓存复用肯定是一大优化。

具体而言,当一个列表项被移出屏幕后,RecyclerView并不会销毁其视图,而是会缓存起来,以提供给新进入屏幕的列表项重用,这种重用不但可以避免重复创建不必要的视图,还可以避免重复执行昂贵的findViewById从而达到的改善性能、提升应用响应能力、降低功耗的效果。

一、核心类

Recycler,这个类是 RecycelerView 缓存复用机制的核心。

在我们常规使用RecyclerView时,与RecyclerView构建动态列表相关联的几个重要类中,AdapterViewHolder负责配合使用,共同定义RecyclerView列表项数据的展示方式,其中:

  • ViewHolder是一个包含列表项视图(itemView)的封装容器,同时也是RecyclerView缓存复用的主要对象。

  • Adapter则提供了数据和视图间的“绑定”关系,其包含以下几个关键方法:

    • onCreateViewHolder:负责创建并初始化ViewHolder及其关联的视图,但不会填充视图内容。
    • onBindViewHolder:负责提取适当的数据,填充ViewHolder的视图内容。

而RecyclerView的缓存机制则可以减少onCreateViewHolder和onBindViewHolder的调用,从而达到减少开销,提高性能的效果。

最优解就是两个方法都不调用,直接复用,次解是只需要调用onBindViewHolder进行数据的绑定,而不需要去重新绑定View,最差解肯定是两个都需要去调用了。

public final class Recycler {final ArrayList<RecyclerView.ViewHolder> mAttachedScrap = new ArrayList<>();ArrayList<RecyclerView.ViewHolder> mChangedScrap = null;final ArrayList<RecyclerView.ViewHolder> mCachedViews = new ArrayList<RecyclerView.ViewHolder>();RecyclerView.RecycledViewPool mRecyclerPool;private RecyclerView.ViewCacheExtension mViewCacheExtension;}

从上述代码可以看出,缓存复用的对象是 ViewHolder。上面五个成员变量就是我们常说的 RecyclerView 的四级缓存,分别是:

  1. mChangedScrap/mAttachedScrap主要用于临时存放仍在当前屏幕可见、但被标记为「移除」或「重用」的列表项其均以ArrayList的形式持有着每个列表项的ViewHolder对象,大小无明确限制,但一般来讲,其最大数就是屏幕内总的可见列表项数。

    • 其中,mChangedScrap主要是为列表项数据发生变化时的动画效果服务的。mChangedScrap缓存中的ViewHolder是需要调用onBindViewHolder方法重新绑定数据的。

    • mAttachedScrap应对的则是剩下的绝大部分场景,比如:像notifyItemMoved、notifyItemRemoved这种列表项发生移动,但列表项数据本身没有发生变化的场景。如果和RecyclerView上的position或者itemId匹配上了,那么认为是干净的ViewHolder,是可以直接拿出来使用的,无需调用onBindViewHolder方法。

  2. mCachedViews,用来缓存移出屏幕之外的 ViewHolder(但有可能很快重新进入屏幕的列表项)。只要position或者itemId对应上了,就无需重新绑定数据,默认大小为2,可以通过  public void setItemViewCacheSize(int size) {
        mRecycler.setViewCacheSize(size);
    }   修改缓存大小
  3. mViewCacheExtension,这一层的创建和缓存完全由开发者自己控制,初始值为 null。这一层很少会用到。
  4. mRecyclerPool,ViewHolder 缓存池。mRecyclerPool主要用于按不同的itemType分别存放超出mCachedViews限制的、被移出屏幕的列表项,其会先以SparseArray区分不同的itemType,然后每种itemType对应的值又以ArrayList的形式持有着每个列表项的ViewHolder对象,每种itemType的ArrayList大小限制默认为5。可通过setMaxRecycledViews(itemType,size)修改大小.

二、Recycler的源码调用

    public final class Recycler {.../*** 尝试通过从Recycler scrap缓存、RecycledViewPool查找或直接创建的形式来获取指定位置的ViewHolder。*/@NullableViewHolder tryGetViewHolderForPositionByDeadline(int position,boolean dryRun, long deadlineNs) {if (mState.isPreLayout()) {// 0 尝试从mChangedScrap中获取ViewHolder对象holder = getChangedScrapViewForPosition(position);...}if (holder == null) {// 1.1 尝试根据position从mAttachedScrap或mCachedViews中获取ViewHolder对象holder = getScrapOrHiddenOrCachedHolderForPosition(position, dryRun);...}if (holder == null) {...final int type = mAdapter.getItemViewType(offsetPosition);if (mAdapter.hasStableIds()) {// 1.2 尝试根据id从mAttachedScrap或mCachedViews中获取ViewHolder对象holder = getScrapOrCachedViewForId(mAdapter.getItemId(offsetPosition),type, dryRun);...}if (holder == null && mViewCacheExtension != null) {// 2 尝试从mViewCacheExtension中获取ViewHolder对象final View view = mViewCacheExtension.getViewForPositionAndType(this, position, type);if (view != null) {holder = getChildViewHolder(view);...}}if (holder == null) { // fallback to pool// 3 尝试从mRecycledViewPool中获取ViewHolder对象holder = getRecycledViewPool().getRecycledView(type);...}if (holder == null) {// 4.1 回调createViewHolder方法创建ViewHolder对象及其关联的视图holder = mAdapter.createViewHolder(RecyclerView.this, type);...}}if (mState.isPreLayout() && holder.isBound()) {...} else if (!holder.isBound() || holder.needsUpdate() || holder.isInvalid()) {...// 4.1 回调bindViewHolder方法提取数据填充ViewHolder的视图内容bound = tryBindViewHolderByDeadline(holder, offsetPosition, position, deadlineNs);}...return holder;}...}    

从上述代码中,可以看到他们的调用顺序为依次从mChangedScrap/mAttachedScrap、mCachedViews、mViewCacheExtension、mRecyclerPool中尝试获取指定位置或ID的ViewHolder对象以供重用,如果全都获取不到则直接重新创建。

参考文章:

https://juejin.cn/post/7344941254236749851?searchId=202411182234361EC6BF29AC9F2C8D6DB5icon-default.png?t=O83Ahttps://juejin.cn/post/7344941254236749851?searchId=202411182234361EC6BF29AC9F2C8D6DB5关于RecyclerView和ListView的缓存对比

https://juejin.cn/post/6844903448974983181?searchId=20241118230728641CF838198392957185icon-default.png?t=O83Ahttps://juejin.cn/post/6844903448974983181?searchId=20241118230728641CF838198392957185 

相关文章:

RecyclerView详解——(四)缓存复用机制

稍微看了下源码和部分文章&#xff0c;在此做个小小的总结 RecyclerView&#xff0c;意思为可回收的view&#xff0c;那么相对于listview&#xff0c;他的缓存复用肯定是一大优化。 具体而言&#xff0c;当一个列表项被移出屏幕后&#xff0c;RecyclerView并不会销毁其视图&a…...

进程 系统调用 中断

进程P通过执行系统调用从键盘接收一个字符的输入&#xff0c;已知此过程中与进程P相关的操作包括&#xff1a; ①将进程P插入就绪队列&#xff1b; ②将进程P插入阻塞队列&#xff1b; ③将字符从键盘控制器读入系统缓冲区&#xff1b; ④启动键盘中断处理程序&#xff1b; …...

演讲回顾丨杭州悦数 CTO 叶小萌:图数据库发展新航向——拥抱 GQL,融合 HTAP,携手 AI

本文为杭州悦数 CTO 叶小萌在“标准智能&#xff1a;新质生产力的原动力”悦数图数据库新产品发布会上的演讲回顾&#xff0c;主题为&#xff1a;《新标准、新期待&#xff1a;展望图数据库发展的关键方向》 各位嘉宾、悦数图数据库的用户以及线上的观众朋友们大家好&#xff0…...

Java安全—JNDI注入RMI服务LDAP服务JDK绕过

前言 上次讲到JNDI注入这个玩意&#xff0c;但是没有细讲&#xff0c;现在就给它详细地讲个明白。 JNDI注入 那什么是JNDI注入呢&#xff0c;JNDI全称为 Java Naming and Directory Interface&#xff08;Java命名和目录接口&#xff09;&#xff0c;是一组应用程序接口&…...

C++:设计模式-单例模式

单例模式&#xff08;Singleton Pattern&#xff09;是一种设计模式&#xff0c;确保一个类只有一个实例&#xff0c;并且提供全局访问点。实现单例模式的关键是防止类被多次实例化&#xff0c;且能够保证实例的唯一性。常见的实现手法包括懒汉式、饿汉式、线程安全的懒汉式等。…...

Softing工业将OPC UA信息建模集成到边缘应用和安全集成服务器中

Softing工业宣布将OPC UA&#xff08;统一架构&#xff09;信息建模集成到其边缘产品系列及安全集成服务器&#xff08;SIS&#xff09;中&#xff0c;这一技术进步使得在工业物联网&#xff08;IIoT&#xff09;应用中的数据集成、交换与控制更加无缝、有效。 &#xff08;OPC…...

WPF中如何让Textbox显示为一条直线

由于Textbox直接使用是一条直线 设置如下代码 可以让Textbox变为直线输入 <Style TargetType"TextBox"x:Key"UsernameTextBoxStyle"><Setter Property"Template"><Setter.Value><ControlTemplate TargetType"{x:Typ…...

VSCode汉化教程【简洁易懂】

我们安装完成后默认是英文界面。 找到插件选项卡&#xff0c;搜索“Chinese”&#xff0c;找到简体&#xff08;更具你的需要&#xff09;&#xff08;Microsoft提供&#xff09;Install。 安装完成后选择Change Language and Restart。...

跨平台多开账号防关联:轻松管理多个账号!

对于跨境电商、独立站以及社媒营销领域&#xff0c;如何高效管理多个账号、确保账号安全是企业面临的重大挑战。那么如何仅用一台电脑就能实现跨平台多开账号呢&#xff1f; 一、为什么需要跨平台多开账号并防关联&#xff1f; 1. 品牌推广&#xff1a;不同平台拥有不同的用户…...

DICOM图像处理:深入解析DICOM彩色图像中的Planar配置及其对像素数据解析处理的实现

引言 在DICOM(Digital Imaging and Communications in Medicine)标准中,彩色图像的存储与显示涉及多个关键属性,其中**Planar Configuration(平面配置)**属性(标签 (0028,0006))尤为重要。当遇到彩色DICOM图像在浏览时被错误地分割为9张小图,而实际应显示为一…...

jupyter notebook的 markdown相关技巧

目录 1 先选择为markdown类型 2 开关技巧 2.1 运行markdown 2.2 退出markdown显示效果 2.3 注意点&#xff1a;一定要 先选择为markdown类型 3 一些设置技巧 3.1 数学公式 3.2 制表 3.3 目录和列表 3.4 设置各种字体效果&#xff1a;加粗&#xff0c;斜体&#x…...

Linux连接网络的三种方式

Linux 连接网络的三种常见方式如下&#xff1a; 桥接模式 原理&#xff1a;虚拟网络接口与物理网络接口或另一个虚拟接口 “桥接”&#xff0c;形成逻辑上的网络交换机&#xff0c;使所有通过该桥接设备的数据包能被转发到桥接组中的所有接口&#xff0c;如同在一个局域网内…...

##继承##

继承的概念 #继承是新模板基于老模板的基础上修改而成&#xff0c;制作新模板时不需要重新开始制作&#xff0c;可以在老模板的基础上进行修改.(如手机版本的换代&#xff0c;软件的版本更新等) #程序也可以继承 继承的格式: class 继承模块&#xff08;被继承模块&#xff…...

2024 APMCM亚太数学建模C题 - 宠物行业及相关产业的发展分析和策略 完整参考论文(1)

摘要 近年来,中国宠物食品行业迅速增长,但面临复杂的国际形势和多变的市场环境,因此科学地分析和预测该行业的发展趋势至关重要。本研究通过构建多个机器学习与统计回归模型,量化分析中国宠物食品行业的关键驱动因素,预测未来宠物食品总产值和出口值。 在数据处理部分,…...

uni-app 修改复选框checkbox选中后背景和字体颜色

编写css&#xff08;注意&#xff1a;这个样式必须写在App.vue里&#xff09; /* 复选框 */ /* 复选框-圆角 */ checkbox.checkbox-round .wx-checkbox-input, checkbox.checkbox-round .uni-checkbox-input {border-radius: 100rpx; } /* 复选框-背景颜色 */ checkbox.checkb…...

使用Notepad++工具去除重复行

使用Notepad工具去除重复行 参考链接&#xff1a;https://blog.csdn.net/londa/article/details/108981396 一 、使用正则表达式 1、对文本进行排序&#xff0c;让重复行排在一起 2、使用正则表达式替换&#xff08;注意&#xff09;^(.*?)$\s?^(?.*^\1$) 在替换时选择正…...

基于Springboot+Vue的救灾物资调动系统 (含源码数据库)

1.开发环境 开发系统:Windows10/11 架构模式:MVC/前后端分离 JDK版本: Java JDK1.8 开发工具:IDEA 数据库版本: mysql5.7或8.0 数据库可视化工具: navicat 服务器: SpringBoot自带 apache tomcat 主要技术: Java,Springboot,mybatis,mysql,vue 2.视频演示地址 3.功能 这个系…...

Unity 使用 Excel 进行配置管理(读Excel配置表、Excel转保存Txt 文本、读取保存的 Txt 文本配置内容)

Unity 使用 Excel 进行配置管理(读Excel配置表、Excel转保存Txt 文本、读取保存的 Txt 文本配置内容) 目录 Unity 使用 Excel 进行配置管理(读Excel配置表、Excel转保存Txt 文本、读取保存的 Txt 文本配置内容) 一、简单介绍 二、实现原理 三、注意事项 四、案例简单步…...

MySQL中索引全详解

第一部分&#xff1a;什么是索引 索引在数据库中就像书的目录&#xff0c;能够快速定位数据位置&#xff0c;从而提升查询效率。没有索引时&#xff0c;数据库查询需要从头到尾扫描整个表&#xff08;称为全表扫描&#xff09;&#xff0c;这在数据量大时非常耗时。有了索引后&…...

vllm serve的参数大全及其解释

以下是 vllm serve 的常见参数说明以及它们的作用&#xff1a; 1. 基本参数 model_tag 说明&#xff1a;用于指定要加载的模型&#xff0c;可以是 Hugging Face 模型仓库中的模型名称&#xff0c;也可以是本地路径。示例&#xff1a;vllm serve "gpt-neo-2.7B"--co…...

K8S认证|CKS题库+答案| 11. AppArmor

目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作&#xff1a; 1&#xff09;、切换集群 2&#xff09;、切换节点 3&#xff09;、切换到 apparmor 的目录 4&#xff09;、执行 apparmor 策略模块 5&#xff09;、修改 pod 文件 6&#xff09;、…...

Opencv中的addweighted函数

一.addweighted函数作用 addweighted&#xff08;&#xff09;是OpenCV库中用于图像处理的函数&#xff0c;主要功能是将两个输入图像&#xff08;尺寸和类型相同&#xff09;按照指定的权重进行加权叠加&#xff08;图像融合&#xff09;&#xff0c;并添加一个标量值&#x…...

spring:实例工厂方法获取bean

spring处理使用静态工厂方法获取bean实例&#xff0c;也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下&#xff1a; 定义实例工厂类&#xff08;Java代码&#xff09;&#xff0c;定义实例工厂&#xff08;xml&#xff09;&#xff0c;定义调用实例工厂&#xff…...

VTK如何让部分单位不可见

最近遇到一个需求&#xff0c;需要让一个vtkDataSet中的部分单元不可见&#xff0c;查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行&#xff0c;是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示&#xff0c;主要是最后一个参数&#xff0c;透明度…...

pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)

目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关&#xff0…...

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中&#xff0c;新增了一个本地验证码接口 /code&#xff0c;使用函数式路由&#xff08;RouterFunction&#xff09;和 Hutool 的 Circle…...

docker 部署发现spring.profiles.active 问题

报错&#xff1a; org.springframework.boot.context.config.InvalidConfigDataPropertyException: Property spring.profiles.active imported from location class path resource [application-test.yml] is invalid in a profile specific resource [origin: class path re…...

Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信

文章目录 Linux C语言网络编程详细入门教程&#xff1a;如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket&#xff08;服务端和客户端都要&#xff09;2. 绑定本地地址和端口&#x…...

【分享】推荐一些办公小工具

1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由&#xff1a;大部分的转换软件需要收费&#xff0c;要么功能不齐全&#xff0c;而开会员又用不了几次浪费钱&#xff0c;借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...

代码规范和架构【立芯理论一】(2025.06.08)

1、代码规范的目标 代码简洁精炼、美观&#xff0c;可持续性好高效率高复用&#xff0c;可移植性好高内聚&#xff0c;低耦合没有冗余规范性&#xff0c;代码有规可循&#xff0c;可以看出自己当时的思考过程特殊排版&#xff0c;特殊语法&#xff0c;特殊指令&#xff0c;必须…...