RecylerView的回收機(jī)制分為兩部分:Cached View和RecycledViewPool
當(dāng)要顯示新的view時,取用順序。
要顯示的View --> View Cache --> RecycledViewPool
View Cache:
default size: 2
View Cache中的ViewHolder還保留了position信息,當(dāng)recyclerview還要顯示position的view時,可以直接使用其中的ViewHolder,不用重新bind。
RecycledViewPool:
每種view type 的default size: 5
RecycledViewPool中的ViewHolder已經(jīng)被清理了position信息,還有一些其他信息,要重新顯示是需要重新bind。
放入RecycledViewPool的條件:
- A view went out of RecyclerView’s bounds during scrolling. (cached view 放不下了)
- Data has changed so that the view is no longer seen. Addition to the pool happens when the disappearance animation finishes.
- An item in the view cache has been updated or removed.
- During a search for a ViewHolder, one was found in scrap or cache with position we want, but turned out to be unsuitable because of the wrong view type or id (if adapter has stable ids).
- The LayoutManager added a view at pre-layout, but didn’t add that view in post-layout.
有兩種條件會阻礙ViewHolder放入RecycledViewPool中:
Recyclability 為false (during animation)
Transient state 為 True (during animator)
如果上述兩個條件都失敗了,則回調(diào)用Adapter的OnFailedToRecycleView,返回True,代表強(qiáng)行回收,返回False,代表放入Pool。
如果一個ViewHolder成功回收了,會調(diào)用onViewRecycled
View Cache和RecylerView的填充順序:

先填充View Cache,再填充Pool
一些例子
例子1:

6,7正在顯示,4,5在View Cache中,3在Pool中,當(dāng)向下滑動時,6進(jìn)入Cache,8從Pool中reuse 3,4從Cache中進(jìn)入Pool。
例子2:

向上滑動時,5還在Cache中,可以直接顯示,7進(jìn)入Cache。
上面的例子中Pool中的ViewHolder始終保持在1個
例子3:

當(dāng)調(diào)用Adapter.notifyDataSetChanged()(或者 Adapter.notifyItemRangeChanged()),會當(dāng)前所有顯示的ViewHolder都進(jìn)入到Pool,但是如果Pool的數(shù)量小于顯示的ViewHolder的數(shù)量,那么有一部分ViewHolder會不能進(jìn)入Holder,這時重新顯示時,不夠的ViewHolder會create,然后再bind。scrollToPosition也會導(dǎo)致需要回收很多Holder到Pool。
一種解決方法是在操作之前增大Pool的capacity,然后操作完之后再設(shè)置回默認(rèn)的。
recyclerView.getRecycledViewPool().setMaxRecycledViews(0, 20);
adapter.notifyDataSetChanged();
new Handler().post(new Runnable() {
@Override
public void run() {
recyclerView.getRecycledViewPool()
.setMaxRecycledViews(0, 1);
}
});