应用心理学硕士365,recyclerView的优点和复⽤机制
⼀、RecyclerView是什么
RecycleView是Android5.0后⾕歌推出的⼀个⽤于在有限的窗⼝中展⽰⼤量数据集的控件,位于support-v7包中。它可以实现与ListView和GridView⼀样的效果,提供了⼀种插拔式的体验,⾼度的解耦,异常的灵活,只需设置其提供的不同的LayoutManager,ItemAnimator和ItemDecoration,就能实现不同的效果。
⼆、RecyclerView的优点
1、⽀持局部刷新。
好好学习天天向上英语怎么说
2、可以⾃定义item增删时的动画。
3、能够实现item拖拽和侧滑删除等功能。
4、默认已实现View的复⽤,⽽且回收机制更加完善。
三、RecyclerView回收复⽤机制浅析
R ec yc ler View回收复⽤机制浅析
RecyclerView 基本上已经成为了开发中常⽤的⼀个组件,通过其提供的强⼤能⼒,能实现各种需要的列表类效果。灵活的同时,要⽤好却也不容易,为了⾼效实现需求,避免掉到各种不明所以的坑⾥⾯,这⾥有必要对其回收复⽤机制做⼀个探究。
本⽂将带着下⾯这⼏个⽅⾯的问题来探究。tips:结合源码⾷⽤更佳。
开始分析回收复⽤机制之前,先提⼏个问题:
传闻中的七公主主题曲
Q1:如果向下滑动,新⼀⾏的5个卡位的显⽰会去复⽤缓存的 Vie wHold e r,第⼀⾏的5个卡位会移出屏幕被回收,那么在这个过程中,是先进⾏复⽤再回收?还是先回收再复⽤?还是边回收边复⽤?也就是说,新⼀⾏的5个卡位复⽤的 Vie wHold e r 有可能是第⼀⾏被回收的5个卡位吗?
第⼆个问题之前,先看⼏张图⽚:
单词翻译软件image.png
这边的理解先向下滑动,指的是⼿指向上滑动,⼀直到List的最底层,这边向上或者向下,指的是RecyclerView的顶端和底端小高考查分
⿊框表⽰屏幕,RecyclerView 先向下滑动,第三⾏卡位显⽰出来,再向上滑动,第三⾏移出屏幕,第⼀⾏显⽰出来。我们分别在 Adapter 的onCreateViewHolder() 和 onBindViewHolder() ⾥打⽇志,下⾯是这个过程的⽇志:
image.png
红框1是 RecyclerView 向下滑动操作的⽇志,第三⾏5个卡位的显⽰都是重新创建的 ViewHolder ;红框2是再次向上滑动时的⽇志,第⼀⾏5个卡位的重新显⽰⽤的 ViewHolder 都是复⽤的,因为没有 cre
ate viewHolder 的⽇志,然后只有后⾯3个卡位重新绑定数据,调⽤了onBindViewHolder();那么问题来了:
Q2: 在这个过程中,为什么当 Re cycle r Vie w 再次向上滑动重新显⽰第⼀⾏的5个卡位时,只有后⾯3个卡位触发了 onB ind Vie wHold e r() ⽅法,重新绑定数据呢?明明5个卡位都是复⽤的。
在上⾯的操作基础上,我们继续往下操作:
image.png
在第⼆个问题操作的基础上,⽬前已经创建了15个 ViewHolder,此时显⽰的是第1、2⾏的卡位,那么继续向下滑动两次,这个过程的⽇志如下:
image.png
红框1是第⼆个问题操作的⽇志,在这⾥截出来只是为了显⽰接下去的⽇志是在上⾯的基础上继续操作的;
红框2就是第⼀次向下滑时的⽇志,对⽐问题2的⽇志,这次第三⾏的5个卡位⽤的 ViewHolder 也都是复⽤的,⽽且也只有后⾯3个卡位触发了onBindViewHolder() 重新绑定数据;
红框3是第⼆次向下滑动时的⽇志,这次第四⾏的5个卡位,前3个的卡位⽤的 ViewHolder 是复⽤的,
后⾯2个卡位的 ViewHolder 则是重新创建的,⽽且5个卡位都调⽤了 onBindViewHolder() 重新绑定数据;
那么,
Q3:接下去不管是向上滑动还是向下滑动,滑动⼏次,都不会再有 onC r e ate Vie wHold e r() 的⽇志了,也就是说 Re cycle r Vie w 总共创建了17个 Vie wHold e r,但有时⼀⾏的5个卡位只有3个卡位需要重新绑定数据,有时却⼜5个卡位都需要重新绑定数据,这是为什么呢?
如果明⽩ RecyclerView 的回收复⽤机制,那么这三个问题也就都知道原因了;反过来,如果知道这三个问题的原因,那么理解 RecyclerView 的回收复⽤机制也就更简单了;所以,带着问题,在特定的场景下去分析源码的话,应该会⽐较容易。
源码分析
其实,根据问题2的⽇志,我们就可以回答问题1了。在⽬前显⽰1、2⾏,
ViewHolder 的个数为10个的基础上,第三⾏的5个新卡位要显⽰出来都需要重新创建 ViewHolder,也就是说,在这个向下滑动的过程,是5个新卡位的复⽤机制先进⾏⼯作,然后第1⾏的5个被移出屏幕的卡位再进⾏回收机制⼯作。猴子捞月英文
rerved是什么意思
那么,就先来看看复⽤机制的源码
复⽤机制
image.png
image.png
image.png
这个⽅法是复⽤机制的⼊⼝,也就是 Recycler 开放给外部使⽤复⽤机制的api,外部调⽤这个⽅法就
苏州网络培训可以返回想要的 View,⽽⾄于这个 View 是复⽤⽽来的,还是重新创建得来的,就都由 Recycler 内部实现,对外隐藏。
tryGetViewHolderForPositionByDeadline()
所以,Recycler 的复⽤机制内部实现就在这个⽅法⾥。
分析逻辑之前,先看⼀下 Recycler 的⼏个结构体,⽤来缓存 ViewHolder 的。
image.png
mAttachedScrap: ⽤于缓存显⽰在屏幕上的 item 的 ViewHolder,场景好像是 RecyclerView 在 onLayout 时会先把 children 都移除掉,再重新添加进去,所以这个 List 应该是⽤在布局过程中临时存放 children 的,反正在 RecyclerView 滑动过程中不会在这⾥⾯来找复⽤的ViewHolder 就是了。
mChangedScrap: 这个没理解是⼲嘛⽤的,看名字应该跟 ViewHolder 的数据发⽣变化时有关吧,在 RecyclerView 滑动的过程中,也没有发现到这⾥找复⽤的 ViewHolder,所以这个可以先暂时放⼀边。
mCachedViews:这个就重要得多了,滑动过程中的回收和复⽤都是先处理的这个 List,这个集合⾥存的 ViewHolder 的原本数据信息都在,所以可以直接添加到 RecyclerView 中显⽰,不需要再次重新 onBindViewHolder()。
mUnmodifiableAttachedScrap: 不清楚⼲嘛⽤的,暂时跳过。
mRecyclerPool:这个也很重要,但存在这⾥的 ViewHolder 的数据信息会被重置掉,相当于 ViewHolder 是⼀个重创新建的⼀样,所以需要重新调⽤ onBindViewHolder 来绑定数据。
mViewCacheExtension:这个是留给我们⾃⼰扩展的,好像也没怎么⽤,就暂时不分析了。
image.png
第⼀步很简单,position 如果在 item 的范围之外的话,那就抛异常吧。继续往下看
image.png
如果是在 isPreLayout() 时,那么就去 mChangedScrap 中找。
那么这个 isPreLayout 表⽰的是什么?,有两个赋值的地⽅。
image.png
emmm,看样⼦,在 LayoutManager 的 onLayoutChildren 前就会置为客房服务员英文
fal,不过我还是不懂这个过程是⼲嘛的,滑动过程中好像
mState.mInPreLayou = fal,所以并不会来这⾥,先暂时跳过。继续往下。
image.png
跟进这个⽅法看看
image.png
⾸先,去 mAttachedScrap 中寻找 position ⼀致的 viewHolder,需要匹配⼀些条件,⼤致是这个 viewHolder 没有被移除,是有效的之类的条件,满⾜就返回这个 viewHolder。
所以,这⾥的关键就是要理解这个 mAttachedScrap 到底是什么,存的是哪些 ViewHolder。
⼀次遥控器按键的操作,不管有没有发⽣滑动,都会导致 RecyclerView 的重新 onLayout,那要 layout 的话,RecyclerView 会先把所有children 先 remove 掉,然后再重新 add 上去,完成⼀次 layout 的过程。那么这暂时性的 remove 掉的 viewHolder 要存放在哪呢,就是放在这个 mAttachedScrap 中了,这就是我的理解了。
紫色英文
所以,感觉这个 mAttachedScrap 中存放的 viewHolder 跟回收和复⽤关系不⼤。
⽹上⼀些分析的⽂章有说,RecyclerView 在复⽤时会按顺序去 mChangedScrap, mAttachedScrap 等等缓存⾥找,没有找到再往下去找,从代码上来看是这样没错,但我觉得这样表述有问题。因为就我们这篇⽂章基于 RecyclerView 的滑动场景来说,新卡位的复⽤以及旧卡位的回收机制,其实都不会涉及到mChangedScrap 和 mAttachedScrap,所以我觉得还是基于某种场景来分析相对应的回收复⽤机制会⽐较好。就像mChangedScrap 我虽然没理解是⼲嘛⽤的,但我猜测应该是在当数据发⽣变化
时才会涉及到的复⽤场景,所以当我分析基于滑动场景时的复⽤时,即使我对这块不理解,影响也不会很⼤。
继续往下看