前言
主要是接上一篇文章,想跟进下RecyclerView的源码,视图从源码层面找到解决RecyclerView+GridLayoutManager组合导致的滑动卡顿问题。
RecycleView在滑动的过程中,需要不断的创建、绑定item、绘制item,这里就不得不了解下recycleView的缓存机制。
缓存机制
其实关于recycleView的缓存机制,网上有很多相关文章:下面推荐几篇我自己看的
RecyclerView 体验优化及入坑总结
【进阶】RecyclerView源码解析(二)——缓存机制
RecyclerView回收和复用机制分析
这里就不做多赘述了。
下面就说一下自己所get到的一些点:
首先要了解recycleView的基本缓存机制:比如是在RecyclerView.Recycler中实现缓存,知道几层缓存对应的数组;
缓存的单位是ViewHolder;tryGetViewHolderForPositionByDeadline()方法是缓存逻辑的入口,recycleViewHolderInternal()是用来更新缓存的;
其次就可以在这次方法打上断点,观察RecycleView.Recycler中的mCachedViews和mScrop两个数组中的元素变化,观察方法的调用顺序等;
For Example:
最后你就已经对recycleView的缓存过程有了很深的了解了,能够知道什么时候使用缓存,什么时候需要创建,是否需要预创建等等。了解了之后,你就会知道其实google工程师写代码时的想法、逻辑等跟我们平时写代码区别真的不大。
下面说下我所理解到几点:
1、mCachedViews和RecyclerPool
mCachedViews是使用position进行匹配的
如果RecyclerView.this.mAdapter.hasStableIds()为true,也可以根据item的id、type进行匹配
mRecyclePool是根据itemType进行匹配的
@Nullable
public RecyclerView.ViewHolder getRecycledView(int viewType) {
//根据viewType获取相对应的ArrayList,如果该list不为空,则返回一个ViewHolder.
RecyclerView.RecycledViewPool.ScrapData scrapData = (RecyclerView.RecycledViewPool.ScrapData)this.mScrap.get(viewType);
if (scrapData != null && !scrapData.mScrapHeap.isEmpty()) {
ArrayList<RecyclerView.ViewHolder> scrapHeap = scrapData.mScrapHeap;
return (RecyclerView.ViewHolder)scrapHeap.remove(scrapHeap.size() - 1);
} else {
return null;
}
}
每个itemType对应只能缓存5个ViewHolder.