用户名
Email
论坛
潜水/灌水快乐,沉淀知识,认识更多同行。
ToB圈子
加入IT圈,遇到更多同好之人。
朋友圈
看朋友圈动态,了解ToB世界。
ToB门户
了解全球最新的ToB事件
博客
Blog
排行榜
Ranklist
文库
业界最专业的IT文库,上传资料也可以赚钱
下载
分享
Share
导读
Guide
相册
Album
记录
Doing
帖子
本版
文章
帖子
ToB圈子
用户
免费入驻
产品入驻
解决方案入驻
公司入驻
案例入驻
登录
·
注册
只需一步,快速开始
账号登录
立即注册
找回密码
用户名
自动登录
找回密码
密码
登录
立即注册
首页
找靠谱产品
找解决方案
找靠谱公司
找案例
找对的人
专家智库
悬赏任务
圈子
SAAS
IT评测·应用市场-qidao123.com
»
论坛
›
职场与人生
›
IT职场那些事
›
RecyclerView的缓存机制(面试常客)
RecyclerView的缓存机制(面试常客)
玛卡巴卡的卡巴卡玛
金牌会员
|
2025-3-21 00:04:04
|
显示全部楼层
|
阅读模式
楼主
主题
988
|
帖子
988
|
积分
2964
在构建滚动列表时,我们常首选RecyclerView,出于它良好的缓存复用机制。
核心机制
RecyclerView的缓存机制又称回收复用机制,RecyclerView构建列表视图分为以下三步:
第一步的创建ViewHolder是RecyclerView构建视图时最耗时的操作,而RecyclerView正是因为做到了缓存复用,从而减少调用创建ViewHolder的次数。
当列表被创建时结构如下,每个ViewHolder中的A、B代表差别的View种类(ViewType):
当我们滚动第一个ViewHolder(此处简称p0)到屏幕以外时,它会被存入mCachedViews中:
此处被回收的p0依旧保存着之前的数据,各种内部状态没有被重置。
假如我们向上滚动,被缓存的p0会从mCachedViews缓存区中移回列表:
因此不需要重复CreateViewHolder和BindViewHolder,减少了耗时。
可见,缓存区是用来存储最近脱离屏幕区的ViewHolder。 这些ViewHolder因为出于屏幕区的界限,更容易因为用户的滚动和抖动被重新显示,因此更需要被快速的加载到视图中。
缓存区存储ViewHolder的默认大小为2,开发者可根据实际需求更改大小。
当缓存区已满,而有新的ViewHolder被放入缓存区时,最先被置入缓存区的ViewHolder会被移到mRecyclerPool中:
进入mRecyclerPool的ViewHolder各种内部状态会被重置,如position会被置为-1,可理解为与之前的数据已解绑;图中的A和B表示差别的ViewType,每个能存储5个ViewHolder,这个大小也是可以被修改的。
分析完列表移出ViewHolder的过程,我们反过来看移入ViewHolder的:
假设此时有一个新的范例为B的ViewHolder(简称p7)要移入屏幕区。
起首查看缓存区中是否有可以复用的ViewHolder。这是因为被放入此处的ViewHolder是不需要重置数据的,因此优先思量这里的ViewHolder,假如有相同的position,就会被取出复用。此处的逻辑和前面p0重新移入的逻辑相同;
图中的例子position=7,与缓存区中的两个ViewHolder的position都不相同,因此无法复用;接下来查看循环池中的ViewHolder。因为View范例为B的循环池中没有ViewHolder,所以依然无法复用;此时我们只能重新走Create和Bind的方法。
假如循环池中有相同范例的ViewHolder:
会从循环池中取出复用,因为被放入循环池中的ViewHolder都是被重置了的,虽然不消走Create方法,但是重新的Bind还是要有的。
是否可以只用一种ViewType?
对于差别的ViewType我们有差别的循环池,那我们是否可以只用一种ViewType,延伸这一个循环池,提高回收复用率?
起首是
可读性和可维护性会变差
。因为差别的ViewType通常数据结构和视图样式方式差别,假如为了让一种ViewType都适配他们,代码肯定会变得很乱。
其次是
不消懒加载,增加调用耗时;使用懒加载,无法克制视图切换耗时
。起首因为ViewType的数据结构和视图样式等诸多内容不尽相同,假如一次全部加载内存开销必然很大,因此我们使用懒加载的方式最为合适,只有需要的时间才取出使用;
但因为我们把原本应该设计为差别的ViewType都塞进了一个ViewType,导致会一次加载所有原本差别的ViewType,无法使用懒加载克制这一征象;
而同时因为ViewType视图样式差别,肯定要重新inflate差别的视图样式,根本没有减少耗时。
RecyclerView缓存机制失效的环境
重写Adapter的onFailedToRecycleView
起首查看RecyclerView的源码:
在是否回收ViewHolder的判断中包罗两个条件:boolean值forceRecycle和isRecyclable方法。我们起首查看后者代码:
后者的isRecyclable方法获取到的是一个名为TransientState的值(直译:临时状态)。当某个ViewHolder中的某个View在做属性动画时,这个值会属性动画开始和竣事时被设置:
这么来说,假如一个ViewHolder在脱离显示区时,同时内部有恣意一个view在做属性动画,TransientState的值就会是false,isRecyclable方法返回的也是false,这个ViewHolder就无法被存储到缓存区或循环池中。
这种环境最容易出现在ViewHolder中存在循环属性动画的场景。假如没有对这个循环属性动画做处理,那么就会出现缓存机制失效的环境。如dy中的专辑旋转动画:
而是否回收ViewHolder的判断中,前者forceRecycle是根据onFailedToRecycleView方法设定的,我们可以重写这个方法:
override fun onFailedToRecycleView(holder: MyViewHolder?): Boolean {
return true
}
复制代码
onBindViewHolder中重置View的动画属性
为什么Android要设计ViewHolder中的View的属性动画不能被回收,要我们如此大费周章?
这么设计的原因是防止ViewHolder被复用时之前的动画状态被保存。因此我们可以在重新绑定ViewHolder的onBindViewHolder方法中,重置View的动画属性,如偏转角度(Rotation)、透明度(Alpha)等。
RecyclerView的特殊复用机制
循环池(mRecyclerPool)可以服务于多个RecyclerView。当其他RecyclerView中拥有循环池中相同的ViewType时,他们都可以使用这个循环池。
参考
Android RecyclerView的缓存机制_哔哩哔哩_bilibili
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
本帖子中包含更多资源
您需要
登录
才可以下载或查看,没有账号?
立即注册
x
回复
举报
0 个回复
倒序浏览
返回列表
快速回复
高级模式
B
Color
Image
Link
Quote
Code
Smilies
您需要登录后才可以回帖
登录
or
立即注册
本版积分规则
发表回复
回帖并转播
回帖后跳转到最后一页
发新帖
回复
玛卡巴卡的卡巴卡玛
金牌会员
这个人很懒什么都没写!
楼主热帖
SQL SERVER事务提交回滚
Kubernetes(k8s)Deployment、Statefu ...
基于STM32的手势识别检测
【C++】ZZ1864- 解题精讲
ConcurrentHashMap源码,看我这篇就够 ...
一文读懂,硬核 Apache DolphinSchedul ...
实用五步法教会你指标体系的设计与加工 ...
如何用技术改变生活
数据类型的内置方法
同事写了一个责任链模式,bug 无数... ...
标签云
运维
CIO
存储
服务器
浏览过的版块
公有云
运维.售后
分布式数据库
快速回复
返回顶部
返回列表