当前位置:网站首页>再学RecyclerView的回收复用机制
再学RecyclerView的回收复用机制
2022-07-27 01:15:00 【独饮敌敌畏丶】
1. 背景
之前对RecyclerView的回收机制掌握状态,一直是朦朦胧胧的,知道有四级缓存,也知道四级缓存分别是干嘛的,也知道先从哪取再从哪取,但是,再细一点,就不知道原因了,说白了还是没有学明白,于是又花了时间细心钻研了下
2. 新的收获
之前有几个误区,包括这次也有新的理解,直到这次看完才明白,记录一下
- 四级缓存并不是都用得上,比如滑动的时候就用不到
scrap缓存,实际滑动的时候,一般只用到了两级缓存 mChangedScrap和mAttachedScrap共同点与不同点
共同点是:不参与滑动时的回收复用,只保存重新布局时从RecyclerView分离的ViewHolder,筛选条件都有position或者id
不同点是:mChangedScrap保存的是:无效、未移除、数据发生变化的ViewHolder,而mAttachedScrap保存的是:无效、未移除、数据没有发生变化的ViewHoldermCachedViews默认容量是2,筛选条件为position或者id- 缓存池默认大小是“两个5”,即五种
itemType,每种itemType默认有五个。使用了SparseArray这个数据类型,如下
public static class RecycledViewPool {
private static final int DEFAULT_MAX_SCRAP = 5;
static class ScrapData {
final ArrayList<ViewHolder> mScrapHeap = new ArrayList<>();
int mMaxScrap = DEFAULT_MAX_SCRAP;
}
SparseArray<ScrapData> mScrap = new SparseArray<>();
}
3. 总结下回收复用原理
3.1 回收原理(一般为两个入口)
在RecyclerView重新布局onLayoutChildren()或者填充布局fill()的时候,会先把必要的item与屏幕分离或者移除,并做好标记,保存到list中,在重新布局时,再将ViewHolder拿出来重新一个个放到新的位置上去。
(1)如果是RecyclerView不滚动情况下缓存(比如删除item),重新布局时,把屏幕上的ViewHolder与屏幕分离下来,存放到Scrap中,即发生改变的ViewHolder缓存到mChangedScrap中,不发生改变的ViewHolder存放到mAttachedScrap中;剩下ViewHolder的会按照mCachedViews>RecycledViewPool的优先级缓存到mCachedViews或者RecycledViewPool中。
(2)如果是RecyclerVIew滚动情况下缓存(比如滑动列表),在滑动时填充布局,先移除滑出屏幕的item,第一级缓存mCachedViews优先缓存这些ViewHolder,但是mCachedViews最大容量为2,当mCachedViews满了以后,会利用先进先出原则,把旧的ViewHolder存放到RecycledViewPool中后移除掉,腾出空间,再将新的ViewHolder添加到mCachedViews中,最后剩下的ViewHolder都会缓存到终极回收池RecycledViewPool中,它是根据itemType来缓存不同类型的ArrayList<ViewHolder>,最大容量为5。
3.2 复用原理(一般为1个入口,即fill()方法)
已经有五个缓存RecyclerView的池子,mChangedScrap、mAttachedScrap、mCachedViews、mViewCacheExtension、mRecyclerPool,除了mViewCacheExtension是系统提供给开发者拓展的没有用到之外,还有四个池子是参与到复用流程中的,从fill方法跟踪,核心为tryGetViewHolderForPositionByDeadline()方法
(1)当RecyclerView要拿一个复用的ViewHolder时,如果是预加载,则会先去mChangedScrap中精准查找(分别根据position和id)对应的ViewHolder,如果有就返回;
(2)如果没有就再去mAttachedScrap和mCachedViews中精确查找(先position后id)是不是原来的ViewHolder,如果是说明ViewHolder是刚刚被移除的;
(3)如果不是,则最终去mRecyclerPool找,如果itemType类型匹配对应的ViewHolder,那么返回实例,让它重新绑定数据;
(4)如果mRecyclerPool也没有返回ViewHolder才会调用createViewHolder()重新去创建一个。
这里需要注意:在mChangedScrap、mAttachedScrap、mCachedViews中拿到的ViewHolder都是精准匹配,但是mChangedScrap的是发生了变化的,需要调用onBindViewHolder()重新绑定数据,mAttachedScrap和mCachedViews没有发生变化,是直接使用的,不需要重新绑定数据,而mRecyclerPool中的ViewHolder的内容信息已经被抹除,需要重新绑定数据。所以在RecyclerView来回滚动时,mCachedViews缓存池的使用效率最高。
总的来说:RecyclerView着重在两个场景缓存和回收的优化,
一是:在数据更新时,使用Scrap进行局部更新,尽可能复用原来viewHolder,减少绑定数据的工作;
二是:在滑动的时候,重复利用原来的ViewHolder,尽可能减少重复创建ViewHolder和绑定数据的工作。
最终思想就是,能不创建就不创建,能不重新绑定就不重新绑定,尽可能减少重复不必要的工作。
4. 遇到过的问题
由于回收复用机制,当item过多时会根据itemType进行复用,那么当Item的布局中,有一父容器为ConstraintLayout、子控件比如为TextVIew,TextView的width为0也就是匹配约束,那么当它到了复用的item的时候,width还是匹配约束,但是此时可能宽度不够显示所有的字符,导致字符显示不全。究其原因,是当宽度为0的时候,不会触发measure流程,所以,将宽度改为wrap_content,即可解决此问题。
5. 参考文章
(带着问题学,讲解滑动场景下的回收复用)https://www.jianshu.com/p/467ae8a7ca6e
(非常详细,极力推荐!!!)https://juejin.cn/post/6984974879296585764#heading-2
边栏推荐
- Hcip 13th day notes
- cocos小游戏实战-05-NPC与角色攻击逻辑
- Manually build ABP framework from 0 -abp official complete solution and manually build simplified solution practice
- 食物链(DAY 79)
- Analysis of [paper] pointlanenet papers
- 二叉树(DAY 82)
- Role of thread.sleep (0)
- Common questions and answers of software testing interview (divergent thinking, interface, performance, concept,)
- 最大连续子序列(DAY 77)
- [哈希表] 刷题合集
猜你喜欢

一道数学题,让芯片巨头亏了5亿美金!

Play a parallel multithreaded mcu-mc3172

HCIP第十三天笔记

HCIP第十四天笔记

浅浅梳理一下双轴快排(DualPivotQuickSort)

Worthington木瓜蛋白酶解离系统解决方案
![[paper]PointLaneNet论文浅析](/img/f6/8001be4f90fe15100e0295de02491f.png)
[paper]PointLaneNet论文浅析

使用 WebSocket 实现一个网页版的聊天室(摸鱼更隐蔽)

CS224W fall 1.2 Applications of Graph ML

Cuteone: a onedrive multi network disk mounting program / with member / synchronization and other functions
随机推荐
Worthington果胶酶的特性及测定方案
全网最全的软件测试基础知识整理(新手入门必学)
196. 删除重复的电子邮箱
力扣(LeetCode)207. 课程表(2022.07.26)
cocos小游戏实战-05-NPC与角色攻击逻辑
如何使用DevExpress WPF在WinUI中创建第一个MVVM应用程序?
易灵思T35 FPGA驱动LVDS显示屏
[paper]PointLaneNet论文浅析
How to visit the latest version of burpsuite pro in vain
[binary search simple question] leetcode 35. search insertion position, 69. Square root of X, 367. Effective complete square, 441. Arrange coins
智能指针shared_ptr、unique_ptr、weak_ptr
Use the most primitive method to manually implement the common 20 array methods
AcWing 2074. 倒计数 模拟
cocos小游戏实战-04-碰撞检测与NPC渲染
Abbkine AbFluor 488 细胞凋亡检测试剂盒特点及实验建议
基于.NetCore开发博客项目 StarBlog - (16) 一些新功能 (监控/统计/配置/初始化)
vs2019 中编译和使用 protobuf 库
Portraiture5全新升级版磨皮滤镜插件神器
[二分查找简单题] LeetCode 35. 搜索插入位置,69. x 的平方根,367. 有效的完全平方数,441. 排列硬币
调用JShaman的Web API接口,实现JS代码加密。