当前位置:网站首页>再学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
边栏推荐
- Thread.Sleep(0)的作用
- 水仙花数(DAY 78)
- [SQL simple question] leetcode 627. change gender
- 论构造函数的原型是谁
- 196. 删除重复的电子邮箱
- [动态规划简单题] LeetCode 53. 最大子数组和
- Okaleido tiger is about to log in to binance NFT in the second round, which has aroused heated discussion in the community
- be based on. NETCORE development blog project starblog - (16) some new functions (monitoring / statistics / configuration / initialization)
- Plato Farm全新玩法,套利ePLATO稳获超高收益
- 易灵思T35 FPGA驱动LVDS显示屏
猜你喜欢
![[paper]PointLaneNet论文浅析](/img/f6/8001be4f90fe15100e0295de02491f.png)
[paper]PointLaneNet论文浅析

Zhang Ping, Alibaba cloud Solution Architect: system construction of cloud native digital safety production

Okaleido tiger is about to log in to binance NFT in the second round, which has aroused heated discussion in the community

从ACL 2022 Onsite经历看NLP热点

“date: write error: No space left on device”解决

单例模式(双检锁)

win10/win11无损扩大C盘空间,跨盘合并C、E盘

Cloud development sleeping alarm clock wechat applet source code

抖音服务器带宽有多大,才能供上亿人同时刷?

An error in the fourth edition of the red book?
随机推荐
175. 组合两个表(非常简单)
用最原始的方法纯手工实现常见的 20 个数组方法
使用 WebSocket 实现一个网页版的聊天室(摸鱼更隐蔽)
[SQL简单题] LeetCode 627. 变更性别
IDEA 连接数据库查询数据后控制台表头中文乱码的解决方法
排列与二进制(吉,大)(DAY 84)
2513: Xiao Yong's academic score (common divisor problem)
Inftnews | "traffic + experience" white lining e Digital Fashion Festival leads the new changes of digital fashion
QT编译出来的exe以管理员权限启动
window对象的常见事件
Okaleido tiger is about to log in to binance NFT in the second round, which has aroused heated discussion in the community
[动态规划简单题] LeetCode 53. 最大子数组和
积分发放带给商家的两个帮助
Non global function of lua function
Cloud development sleeping alarm clock wechat applet source code
cocos小游戏实战-05-NPC与角色攻击逻辑
易灵思T35 FPGA驱动LVDS显示屏
智能指针shared_ptr、unique_ptr、weak_ptr
win10/win11无损扩大C盘空间,跨盘合并C、E盘
Zhang Ping, Alibaba cloud Solution Architect: system construction of cloud native digital safety production