RecycleView详解

news2024/9/29 18:13:44

listview缓存请看: listview优化和详解

RecycleView 和 ListView对比:

  1. 使用方法上

ListView:继承重写 BaseAdapter,自定义 ViewHolder 与 converView优化。

RecyclerView: 继承重写 RecyclerView.Adapter 与 RecyclerView.ViewHolder。设置 LayoutManager 来展示不同的布局样式

区别:

ViewHolder的编写规范化,ListView是需要自己定义的,而RecyclerView是规范好的;
RecyclerView复用item全部搞定,不需要像ListView那样setTag()与getTag();
RecyclerView多了一些LayoutManager工作,但实现了布局效果多样化;

2. 动画api

在RecyclerView中自带动画效果,例如:notifyItemChanged(), notifyDataInserted(), notifyItemMoved()等等;同时内置有许多动画API,如果需要自定义动画效果,可以通过实现(RecyclerView.ItemAnimator类)完成自定义动画效果,然后调用RecyclerView.setItemAnimator();

但是ListView并没有实现动画效果,需要在Adapter自己自定义;

3. 缓存区别

ListView和RecyclerView最大的区别在于数据源改变时的缓存的处理逻辑,ListView是二级缓存,而RecyclerView则是更加灵活地采用了四级缓存。

recycleview有四级缓存:

  • mAttachedScrap(屏幕内),用于屏幕内itemview快速重用,不需要重新createView和bindView

  • mCacheViews(屏幕外),保存最近移出屏幕的ViewHolder,包含数据和position信息,复用时必须是相同位置的ViewHolder才能复用,应用场景在那些需要来回滑动的列表中,当往回滑动时,能直接复用ViewHolder数据,不需要重新bindView。

  • mViewCacheExtension(自定义缓存),不直接使用,需要用户自定义实现,默认不实现。

  • mRecyclerPool(缓存池),当cacheView满了后或者adapter被更换,将cacheView中移出的ViewHolder放到Pool中,放之前会把ViewHolder数据清除掉,所以复用时需要重新bindView。

四级缓存完整存取缓存流程是:

  1. 保存缓存流程:

  • 插入或是删除itemView时,先把屏幕内的ViewHolder保存至AttachedScrap中

  • 滑动屏幕的时候,先消失的itemview会保存到CacheView,CacheView大小默认是2,超过数量的话按照先入先出原则,移出头部的itemview保存到RecyclerPool缓存池(如果有自定义缓存就会保存到自定义缓存里),RecyclerPool缓存池会按照itemview的itemtype(viewHolder类型)进行保存,每个viewHolder类型缓存个数为5个,超过就会被回收。

  1. 获取缓存流程(getViewFromPos()方法):

  • AttachedScrap中获取,通过pos匹配holder——>获取失败,从CacheView中获取,也是通过pos获取holder缓存
    ——>获取失败,从自定义缓存中获取缓存——>获取失败,从mRecyclerPool中获取
    ——>获取失败,重新创建viewholder——createViewHolder并bindview。

(如果某级缓存获取成功后会对该级缓存进行删除,以免占用缓存)

了解了缓存结构和缓存流程,我们再来看看具体的问题: 滑动10个item,再滑回去,会有几个执行onBindView?

参考文:https://www.cnblogs.com/jimuzz/p/14040674.html

  • 由之前的缓存结构可知,需要重新执行onBindView的只有一种缓存区,就是缓存池mRecyclerPool。

所以我们假设从加载RecyclView开始盘的话(页面假设可以容纳7条数据):

  • 首先,7条数据会依次调用onCreateViewHolder和onBindViewHolder。

  • 往下滑一条(position=7),那么会把position=0的数据放到mCacheViews中。此时mCacheViews缓存区数量为1,mRecyclerPool数量为0。然后新出现的position=7的数据通过postion在mCacheViews中找不到对应的ViewHolder,通过itemtype也在mRecyclerPool中找不到对应的数据,所以会调用onCreateViewHolder和onBindViewHolder方法。

  • 再往下滑一条数据(position=8),如上。

  • 再往下滑一条数据(position=9),position=2的数据会放到mCacheViews中,但是由于mCacheViews缓存区默认容量为2,所以position=0的数据会被清空数据然后放到mRecyclerPool缓存池中。而新出现的position=9数据由于在mRecyclerPool中还是找不到相应type的ViewHolder,所以还是会走onCreateViewHolder和onBindViewHolder方法。所以此时mCacheViews缓存区数量为2,mRecyclerPool数量为1。

  • 再往下滑一条数据(position=10),这时候由于可以在mRecyclerPool中找到相同viewtype的ViewHolder了。所以就直接复用了,并调用onBindViewHolder方法绑定数据。

  • 后面依次类推,刚消失的两条数据会被放到mCacheViews中,再出现的时候是不会调用onBindViewHolder方法,而复用的第三条数据是从mRecyclerPool中取得,就会调用onBindViewHolder方法了。

4)所以这个问题就得出结论了(假设mCacheViews容量为默认值2):

  • 如果一开始滑动的是新数据,那么滑动10个,就会走10个bindview方法。然后滑回去,会走10-2个bindview方法。一共18次调用。

  • 如果一开始滑动的是老数据,那么滑动10-2个,就会走8个bindview方法。然后滑回去,会走10-2个bindview方法。一共16次调用。

但是但是,实际情况又有点不一样。因为Recycleview在v25版本引入了一个新的机制,预取机制。

预取机制,就是在滑动过程中,会把将要展示的一个元素提前缓存到mCachedViews中,所以滑动10个元素的时候,第11个元素也会被创建,也就多走了一次bindview方法。但是滑回去的时候不影响,因为就算提前取了一个缓存数据,只是把bindview方法提前了,并不影响总的绑定item数量。

所以滑动的是新数据的情况下就会多一次调用bindview方法。

5)总结,问题怎么答呢?

  • 四级缓存和流程说一下。

  • 滑动10个,再滑回去,bindview可以是19次调用,可以是16次调用。

  • 缓存的其实就是缓存item的view,在Recycleview中就是viewholder。

  • cachedView就是mCacheViews缓存区中的view,是不需要重新绑定数据的。

其他问题:

  1. 为啥需要Scrap一级缓存?

主要用在插入或是删除itemView时,先把屏幕内的ViewHolder保存至AttachedScrap中,作用在LayoutManager中,它仅仅把需要从ViewGroup中移除的子view设置它的父view为null,从而实现了从RecyclerView中移除操作detachView()。不过如果是全部刷新(适配器的notifyDataSetChanged方法),那么不会走Scrap缓存;

RecycleView 滑动冲突解决:

除了可以参考之前我的文章里提到的两种常用解决方案: https://blog.csdn.net/emmmsuperdan/article/details/79645792

如果是双层滑动嵌套情况,可以优化成NestScrollView嵌套RecyclerView方案:

但是要注意设置RecyclerView.setNestedScrollingEnabled(false)这个方法,用来取消RecyclerView本身的滑动效果。

这是因为RecyclerView默认是setNestedScrollingEnabled(true),这个方法的含义是支持嵌套滚动的。也就是说当它嵌套在NestedScrollView中时,默认会随着NestedScrollView滚动而滚动,放弃了自己的滚动。

RecycleView绘制

可参考文:https://blog.csdn.net/qq_32019367/article/details/114656817

在开始onMeasure的地方,对Rv的宽高Mode做了判断,如果是固定宽和高(Exactly_Mode)或者设置了setHasFixedSize,就直接return开始执行下一步layout,为啥固定宽高不需要measure呢?因为固定宽高,一页子view的数量就确定了,直接做layout摆放就行;因此如果在使用rv时知道是固定宽高,可以提前指定或setHasFixedSize,这样更节省绘制性能;

 protected void onMeasure(int widthSpec, int heightSpec) {
        if (mLayout == null) {
            defaultOnMeasure(widthSpec, heightSpec);
            return;
        }
        if (mLayout.isAutoMeasureEnabled()) {
            final int widthMode = MeasureSpec.getMode(widthSpec);
            final int heightMode = MeasureSpec.getMode(heightSpec);
            mLayout.onMeasure(mRecycler, mState, widthSpec, heightSpec);

            final boolean measureSpecModeIsExactly = widthMode == MeasureSpec.EXACTLY && heightMode ==MeasureSpec.EXACTLY;
            if (measureSpecModeIsExactly || mAdapter == null) {
                return;
            }
        }else {
            if (mHasFixedSize) {
                mLayout.onMeasure(mRecycler, mState, widthSpec, heightSpec);
                return;
            }
            ...}
...
}

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

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

相关文章

【华为OD机试模拟题】用 C++ 实现 - 英文输入法(2023.Q1)

最近更新的博客 【华为OD机试模拟题】用 C++ 实现 - 分积木(2023.Q1) 【华为OD机试模拟题】用 C++ 实现 - 吃火锅(2023.Q1) 【华为OD机试模拟题】用 C++ 实现 - RSA 加密算法(2023.Q1) 【华为OD机试模拟题】用 C++ 实现 - 构成的正方形数量(2023.Q1) 【华为OD机试模拟…

计算机组成原理考研题精选

运算 1 D状态寄存器of,cf,sf,zf看结果,数据总线传输数据,Alu是核心器件,地址寄存器是存储器件 2 (74条消息) 【细碎知识1】浮点数的规格化_SinHao22的博客-CSDN博客_浮点数规格化 (74条消息) IEEE754 浮点数:简读案例秒懂_theR…

数据结构之8种排序算法

文章目录1.插入排序2.希尔排序:3.冒泡排序4.快速排序5.简单选择排序6.堆排序在堆中插入新元素:在堆中删除一个元素:7.归并排序8.基数排序9.外部排序排序算法1.插入排序 每次将一个待排序的记录按其关键字大小插入到前面已经排好序的子序列中…

量子态操作:基于门的三态旋转

R-旋转操作 在量子计算中,RX, RY, RZ门是三种基本的单量子比特旋转门,它们分别绕X轴、Y轴、Z轴旋转量子比特的态矢量。 RX旋转门:绕X轴旋转角度为θ\thetaθ的RX门的矩阵表示为: Rx(θ)(cosθ2−isinθ2−isinθ2cosθ2)R_x(\th…

Python3+Selenium3自动化测试

此前对网页内容进行元素定位的操作,接下来就可以对已经定位的元素进行操作了,一般情况下定位好元素后通过IDE的提示就可以了解到有哪些方法 #coding utf-8 import time from selenium import webdriver from selenium.webdriver.common.by import By dr…

JAVA多线程牌号系统开发与应用

技术:Java等摘要:牌号系统是为解决一些服务业营业大厅排队问题而设计的,它能够有效地提高工作人员的工作效率,也能够使顾客合理的安排等待时间,让顾客感到服务的公平公正。论文首先讨论了牌号系统的背景、意义、应用现…

力扣-订单最多的客户

大家好,我是空空star,本篇带大家了解一道简单的力扣sql练习题。 文章目录前言一、题目:586. 订单最多的客户二、解题1.正确示范①提交SQL运行结果2.正确示范②提交SQL运行结果3.正确示范③提交SQL运行结果4.正确示范④提交SQL运行结果5.其他总…

算法模板总结(自用)

算法模板总结滑动窗口双指针算法数组相关合并两个有序数组左右指针技巧快慢指针技巧字符串相关左右指针反转字符串问题快慢指针替换空格字符问题链表相关快慢双指针删除链表的倒数第N个节点链表相交环形链表链表操作几数之和两数之和四个数组的四数之和三数之和同一数组中四数之…

(十)守恒律(主平衡原理)

守恒律表示了物体中某些物理场量之间的关系,它可表述为:某一时刻 ttt,对于物理场量 Φ\bold\PhiΦ 在物体体积 vvv 上的物质积分,其时间变化率等于另一物理场量 Ψ\bold\PsiΨ(源) 在该体积上的物质积分,与通过物体表面…

AI高效学习路径总结

最近chatgpt爆红,百度近日也官宣了大模型新项目“文心一言”(英文名ERNIE Bot),即将在今年3月面向公众开放,我先期待一波,到时候给同学们说说感受。 这也不是第一次人工智能引起广泛关注了,随着…

外贸人员如何让远程办公和在办公室一样办公

俗话说:“工欲善其事,必先利其器”。作为外贸人员,常用的工具主要分为三大类:客户管理工具、翻译工具、邮箱工具。往往外贸人员会忽略另一类工具:远程类工具。客户管理工具 有了客户管理工具,企业和员工都可…

软件测试之正交法

正交法 通过分析我们发现,对于图中的程序而言,我们要设计81条测试用例,那么有没有一种方法能够使用最小的测试过程集合获得最大的测试覆盖率呢? 1. 概述 1.1 定义 正交法,也叫正交实验法或者正交排列法, 就是使用最小的测试过程集合获得最大的测试覆盖率。 “正交实验”是…

LINUX应用GUI开发C++ 之gtkmm4(1)

目录概述GTKgtkmm安装gtkmm4hello,worldcodelite配置代码解释概述 GTK GTK是一个小部件工具包。GTK创建的每个用户界面都由小部件组成。这是在C语言中使用GObject实现的,GObject是一个面向对象的C语言框架。窗口小部件是主容器。然后通过向窗口中添加按钮、下拉菜…

Android Studio中创建java工程

1. 前言 电脑环境: Ubuntu 18.04 开发工具环境:Android Studio 4.1.3 版本 经常要使用验证Java API, 把配置环境步骤记录一下 2. 创建步骤 2.1 新建一个Android Studio App工程 New ---> New Project ---> 选择一个Activity主题---> Finish 就创建ok 2.2 …

如何防护DDOS攻击

DDOS攻击的趋势呈现出明显的增长趋势,特别是在网络攻击技术的发展和攻击者的技术水平提高的情况下,DDOS攻击的发生频率和规模也在不断增加。此外,随着网络技术的发展,攻击者也可以利用更多的技术手段来实施DDOS攻击,比…

kali环境搭建

一、渗透为什么要使用kali? 1、系统开源 kali linux实际上是开源的操作系统,其中内置了几百种工具而且是免费的,可以非常方便的为测试提供上手即用的整套工具,而不需要繁琐的搭建环境,及收集工具下载安装等步骤 2、系统…

通过OpenAI来做机械智能故障诊断-测试(1)

通过OpenAI来做机械智能故障诊断 1. 注册使用2. 使用案例1-介绍故障诊断流程2.1 对话内容2.2 对话小结3. 使用案例2-写一段轴承故障诊断的代码3.1 对话内容3.2 对话小结4. 对话加载Paderborn轴承故障数据集并划分4.1 加载轴承故障数据集并划分第一次测试4.2 第二次加载数据集自…

【华为OD机试模拟题】用 C++ 实现 - 挑选字符串(2023.Q1)

最近更新的博客 【华为OD机试模拟题】用 C++ 实现 - 货币单位换算(2023.Q1) 【华为OD机试模拟题】用 C++ 实现 - 选座位(2023.Q1) 【华为OD机试模拟题】用 C++ 实现 - 停车场最大距离(2023.Q1) 【华为OD机试模拟题】用 C++ 实现 - 重组字符串(2023.Q1) 【华为OD机试模…

浅谈对于封装、继承与多态的理解(Java)

目录 封装 继承 父类成员的访问 如何在子类中访问父类同名的成员 子类构造方法 代码块在继承上的执行顺序 多态 多态的实现条件 重写 多态的优缺点 面向对象程序的三大特征:封装继承和多态。 封装 封装:将数据和操作数据的方法进行有效…

前置知识-辛几何与辛代数、欧式几何与辛几何、Hamilton量

1.3 Hamilton 系统的辛几何算法 1.3.1 辛几何与辛代数的基本概念(下篇) 定义(辛空间、辛映射) 设 V V V 是定义在实数域 R \mathbb{R} R<