上一篇文章分析RecyclerView刷新机制知道
LayoutManager
在布局子View
时会向Recycler
索要一个ViewHolder
。但从Recycler
中获取一个ViewHolder
的前提是Recycler
中要有ViewHolder
。那Recycler
中是如何有ViewHolder
的呢?
本文会分析两个问题:
RecyclerView
的View
是在什么时候放入到Recycler
中的。以及在Recycler
中是如何保存的。LayoutManager
在向Recycler
获取ViewHolder
时,Recycler
寻找ViewHolder
的逻辑是什么。
即何时存、怎么存
和何时取、怎么取
的问题。何时取
已经很明显了:LayoutManager
在布局子View
时会从Recycler
中获取子View
。 所以本文要理清的是其他3个问题。在文章继续之前要知道Recycler
管理的基本单元是ViewHolder
,LayoutManager
操作的基本单元是View
,即ViewHolder
的itemview
。本文不会分析RecyclerView
动画时view
的复用逻辑。
为了接下来的内容更容易理解,先回顾一下Recycler
的组成结构:
Recycler的组成.png
mChangedScrap
: 用来保存RecyclerView
做动画时,被detach的ViewHolder
。mAttachedScrap
: 用来保存RecyclerView
做数据刷新(notify
),被detach的ViewHolder
mCacheViews
:Recycler
的一级ViewHolder
缓存。RecyclerViewPool
:mCacheViews
集合中装满时,会放到这里。
先看一下如何从Recycler
中取一个ViewHolder
来复用。
从Recycler中获取一个ViewHolder的逻辑
LayoutManager
会调用Recycler.getViewForPosition(pos)
来获取一个指定位置(这个位置是子View布局所在的位置)的view
。getViewForPosition()
会调用tryGetViewHolderForPositionByDeadline(position...)
, 这个方法是从Recycler
中获取一个View
的核心方法。它就是如何从Recycler中获取一个ViewHolder
的逻辑,即怎么取
。方法太长, 我做了很多裁剪:
ViewHolder tryGetViewHolderForPositionByDeadline(int position, boolean dryRun, long deadlineNs) {
...
if (mState.isPreLayout()) { //动画相关
holder = getChangedScrapViewForPosition(position); //从缓存中拿吗?不应该不是缓存?
fromScrapOrHiddenOrCache = holder != null;
}
// 1) Find by position from scrap/hidden list/cache
if (holder == null) {
holder = getScrapOrHiddenOrCachedHolderForPosition(position, dry