最近做项目的时候突然想到一个问题,就是在项目里面使用了多种ViewHolder,但是在onBindView这个方法中,RecyclerView是如何知道我在哪个位置需要的是哪种ViewHolder呢?就这个问题趁机看了一下源码,终于找到了答案,原来RecyclerView的缓存机制是区分type的,也就是Recyclerview.Adapter.getItemViewType()这个方法的返回值来区分的。
那么从哪里开始看RecyclerView的源码呢?
因为View创建出来需要加到RecyclerView中,所以从view的measure、layout中去找,RecyclerView的布局都是交给LayoutManager,这里以LinearLayoutManager为例,从onLayoutChildren开始,调用链为
onLayoutChildren --> fill --> layoutChunk
这里fill、layoutChunk都是布局的核心代码,在layoutChunk开头有这么一段:
View view = layoutState.next(recycler);
这个地方返回一个view,传进去的参数为recycler,大概可以猜到这和缓存有关了,点进去看看:
View next(RecyclerView.Recycler recycler) {
if (mScrapList != null) {
return nextViewFromScrapList();
}
final View view = recycler.getViewForPosition(mCurrentPosition);
mCurrentPosition += mItemDirection;
return view;
}
果然,使用到了recycler.getViewForPosition,这个就是缓存的其实方法,最终看到了tryGetViewHolderForPositionByDeadline这个方法,这里就是缓存逻辑的核心代码,这里只挑重点看:
ViewHolder tryGetViewHolderForPositionByDeadline(int position,
boolean dryRun, long deadlineNs) {
.......
//和动画有关系,而且scrapList是在LayoutManager内部的,和recyclerview关系不大
if (mState.isPreLayout()) {
holder = getChangedScrapViewForPosition(position);
fromScrapOrHiddenOrCache = holder != null;
}