RecycleView的缓存机制

字节4轮面试,3轮都问了RecyclerView 阿里面试总共4轮,其中有3轮面试都问到了RecyclerView的问题。面试的点各不相同,有原理、嵌套问题、有缓存实现,但是最终都是殊途同归,所有的问题都汇集在,如何对RecyclerView做性能优化? 一、RecyclerView第一次layout时,会发生预布局pre-layout吗? 第一次布局时,并不会触发pre-layout。pre-layout只会在每次notify change时才会被触发,目的是通过saveOldPosition方法将屏幕中各位置上的ViewHolder的坐标记录下来,并在 阅读详情

 

一、Recyclerview的缓存类

RecycleView的四级缓存是由三个类共同作用完成的,Recycler、RecycledViewPool和ViewCacheExtension。Recycler用于管理已经废弃或者与RecyclerView分离的ViewHolder,这里面有两个重要的成员,为可以看见的屏幕的内部缓存成员mAttachedScrap、mChangedScrap和滑出屏幕外的外部缓存成员mCachedViews二者共同完成ViewHolder的缓存;RecycledViewPool类是用来缓存整体所有的ViewHolder,是对mCachedViews缓存的补充;ViewCacheExtension是扩展内的缓存对象,默认不加载,需实现方法getViewForPositionAndType(Recycler recycler, int position, int type)来实现自己的缓存。接下来对四级缓存一步步介绍。

二、Recycler屏幕内部缓存

上面说过屏幕内部缓存包括两个重要的成员mAttachedScrap、mChangedScrap。mChangedScrap表示数据已经改变的viewHolder列表,mAttachedScrap表示未与RecyclerView分离的ViewHolder列表,他是Recycleview的一级缓存,缓存查找中不会调用Recycleview方法onBindViewHolder()。

    public final class Recycler {
        //一级缓存中用来存储屏幕中显示的ViewHolde
        final ArrayList<ViewHolder> mAttachedScrap = new ArrayList<>();
        ArrayList<ViewHolder> mChangedScrap = null;
        //二级缓存中用来存储屏幕外的缓存
        final ArrayList<ViewHolder> mCachedViews = new ArrayList<ViewHolder>();
        //暂可忽略 mAttachedScrap的不可变视图
        private final List<ViewHolder> mUnmodifiableAttachedScrap = Collections.unmodifiableList(mAttachedScrap);
        //当前屏幕外缓存大小,数量为2
        private int mRequestedCacheMax = DEFAULT_CACHE_SIZE;
        int mViewCacheMax = DEFAULT_CACHE_SIZE;
        //四级缓存当二级缓存超过2时候启用
        RecycledViewPool mRecyclerPool;
        //三级缓存扩展类(默认不启用)
        private ViewCacheExtension mViewCacheExtension;

        static final int DEFAULT_CACHE_SIZE = 2;
     }

1、内部缓存的添加

    void scrapView(View view) {
         //根据View获取ViewHolder
        final ViewHolder holder = getChildViewHolderInt(view);
        //判断该ViewHolder是否分离
        if (holder.hasAnyOfTheFlags(ViewHolder.FLAG_REMOVED | ViewHolder.FLAG_INVALID)
                || !holder.isUpdated() || canReuseUpdatedViewHolder(holder)) {
            if (holder.isInvalid() && !holder.isRemoved() && !mAdapter.hasStableIds()) {
                throw new IllegalArgumentException("Called scrap view with an invalid view."
                        + " Invalid views cannot be reused from scrap, they should rebound from"
                        + " recycler pool." + exceptionLabel());
            }
            //未分离的ViewHolder设置false
            holder.setScrapContainer(this, false);
            //添加到未分离的集合mAttachedScrap里面
            mAttachedScrap.add(holder);
        } else {
            if (mChangedScrap == null) {
                mChangedScrap = new ArrayList<ViewHolder>();
            }
            //如果已经分离设置ViewHolder为true
            holder.setScrapContainer(this, true);
            //添加到已经分离的集合mChangedScrap里面
            mChangedScrap.add(holder);
        }
    }

三、Recycler屏幕外部缓存

屏幕的外部缓存是二级缓存,使用的缓存容器变量是mCachedViews,缓存最近回收的ViewHolder,缓存复用时必须匹配position,这个集合里存的 ViewHolder 的原本数据信息都在,所以可以直接添加到 RecyclerView 中显示,不需要再次重新onBindViewHolder()。默认大小是2,最大的缓存大小默认为2个ViewHolder,可以通过Recycleview的setViewCacheSize方法进行设置缓存大小。

	public void setViewCacheSize(int viewCount) {
		mRequestedCacheMax = viewCount;
		updateViewCacheSize();
	}

如果缓存满了的话,就会移除最后一个缓存的缓存加到四级缓存的缓冲池中:

	void recycleCachedViewAt(int cachedViewIndex) {
	   //cachedViewIndex为缓存容器mCachedViews的mCachedViews.size() - 1
		ViewHolder viewHolder = mCachedViews.get(cachedViewIndex);
	   //添加进缓存池
		addViewHolderToRecycledViewPool(viewHolder, true);
		//移除缓存容器mCachedViews中该ViewHolder
		mCachedViews.remove(cachedViewIndex);
	}

四、ViewCacheExtension缓存

ViewCacheExtension缓存是自定义的缓存三级缓存,是一个Recycleview的一个抽象的静态内部内留,给开发者开发,需要直线getViewForPositionAndType抽象方法,默认不会加载,这里不详细说明:

   public abstract View getViewForPositionAndType(Recycler recycler, int position, int type);

五、RecycledViewPool缓存

    void                                      clear() 清空缓存池
    RecyclerView.ViewHolder    getRecycledView(int viewType)    得到一个viewType类型的Item
    void                                      putRecycledView(RecyclerView.ViewHolder scrap)    把viewType类型的Item放入缓存池
    void                                    setMaxRecycledViews(int viewType, int max)设置对应viewType类型的Item的最大缓存数量

    这里看看常用的setMaxRecycledViews方法:

    RecyclerView.RecycledViewPool pool = recyclerView.getRecycledViewPool();
    pool.setMaxRecycledViews(0,10);
    //如果LayoutManager是LinearLayoutManager GridLayoutManager,则需要setRecycleChildrenOnDetach(true)
    //layoutManager.setRecycleChildrenOnDetach(true);
    recyclerView.setRecycledViewPool(pool);

Recycleview的四级缓存图总结如下:

 

六、Recycleview的缓存引起的错乱问题

Recycleview的缓存虽然功能强大,但是有些时候缓存复用能导致页面布局错位,异常,问题出现后通常有以下方法解决:

1、ViewHolder的setIsRecyclable方法

使用ViewHolder的setIsRecyclable方法可以使禁止该ViewHolder的缓存,每个页面都是新的,这种方法简单、快捷,但是也十分暴力数据量大的话会导致滑动顿卡,数据量小的话效果不错。他的原理是通过设置标志位,使其忽略一切缓存。

holder.setIsRecyclable(false);

2、Recycleview的setViewCacheSize方法

通过设置setViewCacheSize的大小可以扩大或者缩小屏幕外的缓存数量,来改善异常问题。

     recyclerView.setItemViewCacheSize(0);//禁用屏幕外缓存,直接使用RecycledViewPool缓存

     recyclerView.setItemViewCacheSize(20);//扩大屏幕外缓存

3、 Recycleview的setRecycledViewPool方法

通过设置指定类型的ViewHolder的缓存池中能缓存的数量来限制。

    pool.setMaxRecycledViews(0,0);//TYPE为0,缓存数量为0
	
    recyclerView.setRecycledViewPool(pool);//给Recycleview设置缓存池对象

4、通过新增一个boolean类型变量维护在接口返回数据Bean类中

每次选中或者点击设置数据的布尔值为true,非选中或者执行状态置为false,这样每次的UI展示都是根据接口维护数据来判断,不会引起错位问题。

5、通过内部维护Map集合

将选中和非选中的状态存储在Map集合中,位置position作为key,状态作为value,每次UI展示操作都从集合中获取position对应,的值,进行状态重置。

总结:

RecyclerView的四级缓存包括:

  1. 一级缓存:mAttachedScrap、mChangedScrap
  2. 二级缓存:mCacheViews
  3. 三级缓存:mViewCacheExtension
  4. 四级缓存:mRecyclerPool

一级缓存为屏幕内缓存,二级缓存为屏幕外缓存,三级缓存为自定义缓存,四级缓存为缓存池缓存。一二三即缓存直接不需要重新绑定View,四级缓存需要绑定Holder设置数据。禁用缓存可以使用ViewHolder的setIsRecyclable方法。

参考文献:Bugly-Android ListView 与 RecyclerView 对比浅析--缓存机制

 

 

 

RecyclerView性能优化及高级使用 最近研究应用流畅度专题时,发现RecyclerView里边的坑真多,有很多可以优化的点,在理解优化点之前,最好对RecyclerView的缓存机制有一些了解,比如得知道CacheView和RecycledViewPool的区别和联系,RecyclerView的绘制流程有一定了解,再来谈RecyclerView的性能提升。缓存机制可以看看这篇文章:基于滑动场景解析RecyclerView的回收复用机... 阅读详情

相关推荐

Android开发学习笔记之RecycleView缓存机制

文章目录Android开发学习笔记之RecycleView缓存机制概述为什么需要缓存机制呢?RecycleView的缓存机制基本原理数据集发生变化item滑出屏幕针对RecycleView的缓存机制的优化策略 Android开发学习笔记之RecycleView缓存机制 概述 RecycleView作为Android开发中最为常见的一个View,其布局灵活,功能强大,在日常的开发中,已经基本取代了List View和GridView成为了我们在使用列表的不二之选。但是,尽管使用频率相当高,在开发中使用Recy

qq_36425800的博客 971

Android 开发中一些有趣的用法

1、RecyclerView.ViewHolder#setIsRecyclable // 对这个holder单独强制关闭复用 holder.setIsRecyclable(false); 用这个时,不能在通用的地方用,不然很很很影响性能,要确保只在特定的 holder 使用,比如在 onBindViewHolder 时,通过数据判断,在某个特定 holder 才使用,下面是通过 debug 输出...

zeqiao的博客 1785

【android】RecyclerListView、RecyclerPagerSnapHelper、AsyncLayoutInflater、setMaxRecycledViews的使用方法

RecyclerView 是 Android 中一个高效的列表控件,但是在使用过程中可能会出现卡顿、内存泄漏等问题,为了避免这些问题,Android 在不同版本中陆续提供了一些优化 RecyclerView 内存的措施:Android 7.0(API 24):引入了,它允许将 RecyclerView 的视图缓存移出堆内存,并采用了更高效的视图绑定方式,以提高性能和减少内存使用。Android 7.1(API 25):引入了。

资深全栈开发工程师 596

解决RecyclerView代码复用问题

方法一. holder.setIsRecyclable(false);//取消复用,但会造成卡顿 方法二.在Adapter下(就是添加一个标记集合,当是否点击,如果是就添加到这个集合中,否就移除,再判断一次当前是否在这个集合中,是就显示点击的状态,否就显示未点击状态) privateList Livelist=new ArrayList   onBindViewHolder下 playv

rhyme_op_lph的博客 1万+

ANSYS拓扑优化基础实例

唐深51CAE 2018/6/10 拓扑优化在工程设计中,常用于机械结构概念设计和轻量化设计,ANSYS通用有限元分析软件提供了强大的拓扑优化功能,本文将通过一个简单实例进行展示。 一、赵州桥 赵州桥又称安济桥,坐落在河北省赵县洨河上,建于隋朝年间公元595年~605年,由著名匠师李春设计建造,距今已有约1500年的历史,是当今世界上现存最早、保存最完整的古代敞...

TQT_CAE的博客 6026

基于Simulink的魔术公式轮胎动力学仿真

本篇博文主要用来记录汽车系统动力学课程的学习,仅供课程阶段参考,与实际工程应用还有较大距离。基于Simulink的魔术公式轮胎动力学仿真本实例主要有以下任务。1.建立魔术公式轮胎动力学仿真模型。2.绘制不同载荷下的轮胎纵向力—滑动率关系曲线。3.绘制不同载荷下的轮胎侧向力—侧偏角关系曲线。4.绘制不同载荷下的轮胎回正力矩—侧偏角关系曲线。提示:以下是本篇文章正文内容,下面案例可供参考。

shy_201992的博客 6937

RecycleView 缓存机制总结

一、RecycleView的四级缓存 1.第一级缓存mChangedScrap(ArrayList<ViewHolder>)和mAttachedScrap (ArrayList<ViewHolder>),主要用于缓存屏幕内的ViewHolder,在用户调用notifyxxx()的时候,直接取数据刷新页面。mChangedScrap和mAttachedScrap 的区别是当调用不同的notifyxxx()方法刷新页面的时候,缓存数据有些放在mChangedScrap,有些放在mAtta

zzq2006的博客 637

01-认识脑电信号及相关信号的预处理过程

脑电信号处理过程脑电实验为什么要预处理预处理方法降采样如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入 脑电实验 本博客主要是记录基于脑电信号的情绪识别方法的研究...

脑机交流者的博客 7658

RecycleView 缓存机制

参考文献 您可以先看看下面的文章后,再看博主的也许有更大的收货. 每日一问 | RecyclerView的多级缓存机制,每级缓存到底起到什么样的作用? 深入理解 RecyclerView 的缓存机制 RecyclerView缓存原理,有图有真相 前言 本文所分析的源码版本: androidx.recyclerview:recyclerview:1.1.0 缓存本质思想: 缓存是一种空间换时间的算法思想. recyclerview缓存了什么: 缓存了ViewHolder对象.

不会写代码的丝丽 1079

基于深度学习YOLOv10的障碍物检测系统

为了方便用户使用,我们将开发一个图形用户界面(GUI),允许用户上传图像或视频流并查看检测结果。我们使用PySide6开发GUI界面,它是Qt框架的Python绑定,适用于开发跨平台的桌面应用程序。本文详细介绍了如何基于YOLOv10模型构建一个障碍物检测系统,包括数据集准备、模型训练和推理到图形用户界面的开发。通过这一系统,用户可以方便地上传图像或视频流并进行障碍物检测,广泛应用于自动驾驶、机器人导航等领域。

斌擎科技 1051

SAP MD09 事务码中的物料需求追溯详解

物料需求追溯是指在物料需求计划中,追踪特定物料的需求来源和满足方式的过程。它帮助企业确定每个需求(如销售订单、独立需求、预留等)是由哪些供应元素(如库存、生产订单、采购订单等)来满足的。通过这种追溯,企业可以了解需求和供应之间的关系,从而优化生产和采购计划,减少库存积压,提升供应链效率。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1193

RecycleView的理解及四层缓存机制

定义:RecyclerView是Android Jetpack中的一个高级滚动列表组件,用于高效地展示大量数据集。它的设计目标是解决ListView在性能和灵活性上的不足,通过视图回收机制来最小化内存占用并保证滚动的流畅性。它的强大之处在于其高度解耦的插件化架构,主要依赖于四个核心组件协同工作:Adapter:负责将数据集合中的每个数据项转换为可视化的视图项(ItemView)。它创建ViewHolder并完成数据绑定。ViewHolder:作为Adapter的内部类,用于缓存ItemView内部子视图的引

weixin_41553587的博客 822

逻辑回归:利用Python实现二分类算法

通过使用Python编写的代码,我们可以训练逻辑回归模型并进行预测。接下来,我们将实现逻辑回归算法的训练函数。训练函数将接受训练数据集X和对应的标签y,以及学习率alpha和迭代次数num_iterations。训练完成后,我们可以使用训练得到的参数theta来进行预测。在这个例子中,我们有一个包含4个样本的训练数据集X,每个样本有两个特征。在这个例子中,如果预测概率大于等于0.5,则预测为类别1,否则预测为类别0。现在,我们可以使用训练函数来训练模型。根据给定的样本x_new,预测函数将返回相应的类别。

XlltEditor的博客 326

RecycleView与ListView的区别以及RecycleView缓存机制总结

RV和LV的区别 LV: 继承并重写BaseAdapter类,布局效果单一 自定义ViewHolder和convertView的复用优化 可以通过addHeaderView()和addFooterView()添加下拉刷新的头部view与上拉加载更多的底部view,且不会影响Adapter的编写 在刷新条目数据时通常使用notifyDataSetChanged()方法这种刷新数据是全局刷新的方式,...

fafaws3000的博客 409

61、增益调度控制器:原理、建模与调优

本文详细介绍了增益调度控制器的原理、建模方法和调优流程。增益调度是一种针对非线性系统的控制策略,通过在不同工作点使用不同的线性控制器实现全局控制。文章涵盖了在Simulink中使用Control System Toolbox模块建模的具体步骤,以及如何利用systune进行增益调度表的调优。同时,还讨论了实际应用中的注意事项、典型案例(如化学反应器和飞机控制),并与其它控制方法进行了对比。最后,文章展望了增益调度控制器的未来发展趋势,包括与人工智能的结合、多目标优化调优以及实时调优能力的提升。

rgv234567的博客 186

国科大作业考试资料-人工智能原理与算法-2024新编-第十一次作业整理

1、有一位教授想知道学生是否睡眠充足。每天,教授观察学生在课堂 上是否睡觉,并观察他们是否有红眼。教授获得如下的领域知识: (1)没有观察数据时,学生睡眠充足的先验概率为0.7。 (2)给定学生前一天睡眠充足为条件,学生在晚上睡眠充足的概率是0.8;如果前一天睡眠不充足,则是0.3。 (3)如果学生睡眠充足,则红眼的概率是0.2,否则是0.7。 (4)如果学生睡眠充足,则在课堂上睡觉的概率是0.1,否则是0.3。 将这些信息形式化为一个动态贝叶斯网络,使教授可以使用这个网络从观察序列中进行滤波和预

MatsumotoChrikk 1055

View-RecycleView的缓存机制

2.怎么存? 举例LinearLayoutManager,在布局子控件的时候,会先暂时缓存目前所有ViewHolder,调用LayoutMananger将每个ViewHolder缓存到相应的级别 复用机制 举例LinearLayoutManager,在布局的时候,会尝试从缓存中遵循顺序去获取ViewHolder...

qq_21349039的博客 356

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

初步理解RecycleView缓存机制

1.recycleView 官方介绍:A flexible view for providing a limited window into a large data set. 即:为大数据集提供有限窗口的灵活视图 2.缓存层级 源码中对相应缓存方法定义初步看有两个方法: 1. Scrap (view):布局期间进入临时分离状态的子视图。没有完全与父RecycleView完全分离, 如果不需要重新绑定则可以不进行更改,如果视图被

阿呆的博客 228

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

RecycleView滑动、缓存、复用源码分析与优化

RecycleView滑动原理、缓存复用原理 RecycleView如何判读一屏有多少个View? 每加载一个Item进入RecycleView中,就将当前Item高度加到RecycleView中,直到当前bottom大于等于屏幕高度

xiaok的博客 1481

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

Listview与Recycleview的区别-(用法及缓存机制)

用法上的区别 1、listview的用法 继承的时BaseAdapter,需要重写四个方法 不强制使用viewholder 可以直接使用item的点击事件 不用单独设置分隔线 不可以定向刷新某一条数据 示例代码如下:项目代码详见地址: public class MyListAdapter&lt;T&gt; extends BaseAdapter { private static fi...

MarinaTsang的博客 4411

RecycleView的缓存问题

RecycleView的缓存机制,回收和复用

qq_34629725的博客 704

Android中RecycleView的简单介绍

Android近几年面对开发者提供了不少新控件,其中我觉得现在最成功的要属于RecycleView了;下面我给大家分析为什么我觉得他是最成功的。说到RecycleView,不得不提出ListView;ListView在使用的时候我们都知道,在使用的时候需要自定义一个Adapter,这个Adapter的主要作用就是: 1:获取List条目数量 2:获取每一个条目的布局视图 3:条目缓存策略

jike0901xuye的专栏 808
上一篇: GridView横滑效果的实现
下一篇: 设计模式之责任链模式
一杯清泉
博客等级 码龄11年 314粉丝 210原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值