RecyclerView回收复用机制浅析

RecyclerView回收复用机制浅析

RecyclerView 基本上已经成为了开发中常用的一个组件,通过其提供的强大能力,能实现各种需要的列表类效果。灵活的同时,要用好却也不容易,为了高效实现需求,避免掉到各种不明所以的坑里面,这里有必要对其回收复用机制做一个探究。

本文将带着下面这几个方面的问题来探究。tips:结合源码食用更佳。

回收复用机制到底回收复用的是啥

回收复用的单元是Viewholder,我们记得,在使用 ListView 的时候,也用到了 ViewHolder,这两者其实是有区别的。

  • ListView 中使用的 ViewHolder, 仅仅是对 view 的引用,只记录了 view 的实例。

  • RecylerView 中使用的 ViewHolder, 记录的东西,就非常多了。源码注释中是这么写的:A ViewHolder describes an item view and metadata about its place within the RecyclerView。 查看其实现,发现记录了 itemview,view 的当前 position,以前的 position,itemId, itemViewType, 当前的状态 flag 等等,itemview 的状态有(绑定|移除|更新|有效|不可回收|报废返回|暂时分离|移动|隐藏|等等),
    这些组合信息,可以把每一个 itemview 布局状态区分开来,这正是 RecyclerView 具有局部刷新能力而 ListView 只能全量更新的原因。

谁负责回收复用机制

这里也首先从源码入手,结合源码的注释进行学习。

通过源码发现,Recycler 是负责管理废弃的(scrapped)分离的(detached) item进行的复用的。这里解释一下, 所谓废弃的 view,指的是 view 仍然
附加在父 RecyclerView 上, 但是被标记为要删除或者重新绑定或复用的。

Recycler回收复用的能力,可以通过观察其成员变量来理解:

  • ArrayList<ViewHolder> mAttachedScrap 和 mChangedScrap

    还绑定在父 RecyclerView 上的 view 。 当视图滑出屏幕外了,需要在滑入屏幕的地方绑定 view 的时候,就会触发报废 view 的机制;调用数据更新接口也能触发 RecyclerView 重新排列,会对绑定的数据先报废分离,重新绑定。这个时候,也触发了报废 view 的机制,mChangedScrap 中的change指的是item被标记为更新、有动画且动画支持变化(即实现了animateChange方法), 这种情况下, ViewHolders 被添加到 mChangedScrap 中, 其他时候报废的 ViewHolders 会添加到 mAttachedScrap。

  • ArrayList<ViewHolder> mCachedViews

    缓存滑出屏幕的 ViewHolder。
    ViewHolder 被回收的时候,如果已经缓存的 ViewHolder 数量小于最大缓存值(默认为2,可以通过 setItemViewCacheSize() 来修改最大缓存数量),会优先放到 mCachedViews 中。

  • RecycledViewPool mRecyclerPool
    RecyclerViewPool可以在不同的 RecyclerView 里面复用 ViewHolder;如果没有为 RecyclerView 设置 RecyclerViewPool(通过 setRecycledViewPool 方法), 默认会自己设置一个。这里简单分析一些RecyclerViewPool的实现:

    RecyclerViewPool内部持有一个二维的mScrap变量, mScrap 的 key 为 ViewHolder 的 type, value 为一个列表, 表示的是同一 type 的 ViewHolder 实例集合。内部的其他方法为外部提供回收和复用的接口。

  • ViewCacheExtension mViewCacheExtension
    ViewCacheExtension 是一个抽象类, 其只包含

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

这个抽象方法, 该方法为开发者自定义复用机制提供接口,由开发者自行决定 ViewHolder 缓存的实现,并根据 viewtype 和 adapter position 返回 view 给 RecyclerView。

回收复用的机制是怎样的

要了解复用的机制是什么, 着重学习 Recycler 的 getViewForPosition(int position, boolean dryRun) 的方法。下图是其流程图。

st=>start: Start
op1=>operation: 从 changedScrap 中寻找
op2=>operation: 从 attachedScrap 中寻找
op3=>operation: 从 mViewCacheExtension 中寻找
op4=>operation: 从 RecyclerViewPool 中寻找
op5=>operation: 调用 creatViewholder

cond1=>condition: 没找到
cond2=>condition: 没找到
cond3=>condition: 没找到
cond4=>condition: 没找到
o1=>inputoutput: 状态处理
e=>end: End

st->op1->cond1
cond1(yes)->op2->cond2
cond2(yes)->op3->cond3
cond3(yes)->op4->cond4
cond4(yes)->op5->o1->e
cond1(no)->o1
cond2(no)->o1
cond3(no)->o1
cond4(no)->o1

基于这样的回收复用机制, 使用的时候要注意哪些事情

  • RecyclerView 的 item 只要视觉上看起来不一样, 都要重写 adapter 的 getItemViewType 方法。为啥呢?因为回收的 ViewHolder 都是放在 一个 以 viewtype 为 Key 的 List 里面, 如果不重写的话, 拿到的 ViewHolder 由于缓存的 存在, 可能 “残留” 其他视图的元素或属性。
  • 可以用局部刷新的就用局部刷新。
  • mCachedViews默认缓存2个,RecyclerPool默认缓存5个。在同一type可见item比较多且设备性能不错的时候(考虑到屏幕大小一定,交互美感等因素,也不可能无限多),可以适当增大默认缓存值。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容