RecycleView 缓存机制

RecyclerView 的使用:

RecyclerView lv = (RecyclerView) findViewById(R.id.lv);
lv.setLayoutManager(new LinearLayoutManager(getApplicationContext(), LinearLayoutManager.VERTICAL, false));
lv.setAdapter(new MyListAdapter(getApplicationContext()));

setLayoutManager 给 RecyclerView 设置了 mLayout, setAdapter 设置 mAdapter, 清除缓存的一些信息,并 requestLayout. RecyclerView 执行 onLayout 过程中,会调用 mLayout.layoutChildren 方法,然后到 LinearLayoutManager 的 layoutChildren 方法,fill(recycler, mLayoutState, state, false) 再到 layoutChunk 方法中看,第一行代码就是 layoutState.next(recycler), 进去看这个方法,这个方法获取了下一个需要 layout 的 view, 看下源码:

if (mScrapList != null) {
    // mScrapList 不为 null, 则取 mScrapList 中的 View
    return nextViewFromScrapList();
}
// mScrapList 为 null, 则继续查找 view, 从 getViewForPosition, tryGetViewHolderForPositionByDeadline 方法看
final View view = recycler.getViewForPosition(mCurrentPosition);
mCurrentPosition += mItemDirection;
return view;

tryGetViewHolderForPositionByDeadline 方法,主要查缓存 View 的地方

ViewHolder tryGetViewHolderForPositionByDeadline(int position,
        boolean dryRun, long deadlineNs) {
    boolean fromScrapOrHiddenOrCache = false;
    ViewHolder holder = null;
    // 0) 首先从 mChangeScrap 中查
    if (mState.isPreLayout()) {
        holder = getChangedScrapViewForPosition(position);
        fromScrapOrHiddenOrCache = holder != null;
    }
    // 1) 没有找到就从 mAttachView 或 mCacheView 中查
    if (holder == null) {
        holder = getScrapOrHiddenOrCachedHolderForPosition(position, dryRun);
        if (holder != null) {
            // ...
        }
    }
    if (holder == null) {
        final int type = mAdapter.getItemViewType(offsetPosition);
        // 2) 通过 stableIs 在 mAttachView 和 mCacheView 中查
        if (mAdapter.hasStableIds()) {
            holder = getScrapOrCachedViewForId(mAdapter.getItemId(offsetPosition),
                    type, dryRun);
            if (holder != null) {
                // ...
            }
        }
        if (holder == null && mViewCacheExtension != null) {
            // 通过 mViewCacheExtension 查
        }
        if (holder == null) { // 从 mRecyclerPool 中查
            holder = getRecycledViewPool().getRecycledView(type);
            if (holder != null) {
                // ...
            }
        }
        if (holder == null) {
            // 自己创建 View, 也就是我们自己实现的 onCreateViewHolder 方法
            holder = mAdapter.createViewHolder(RecyclerView.this, type);
            // ...
        }
    }

    // ...

    // 设置 layoutParams
    return holder;
}

layout 过程中就是以上面的方式获取缓存的 View, 然后加到 RecyclerView 中。

下面再看滑动过程中 item 是怎么复用的,RecyclerView 的 onTouchEvent 方法 ACTION_MOVE 事件中调用了 mGapWorker.postFromTraversal(this, dx, dy), 接着到 GapWorker 中看,它的 postFromTraversal 方法主要执行了 recycleview.post(this), GapWorker 是一个 Runnable, 那么执行的就是 GapWorker 的 run() 方法,在这里面一直跟进去 prefetch, flushTasksWithDeadline, prefetchPositionWithDeadline, 我们能看到在 prefetchPositionWithDeadline 方法中同样调了 recycler.tryGetViewHolderForPositionByDeadline 来获取缓存中的 ViewHolder, 所以滑动过程中 item 的复用就是这样实现的。

好吧,分析的不是很清晰,先到这里吧,继续看源码(^▽^)

猜你喜欢

转载自blog.csdn.net/hexiaosa91/article/details/82291859
今日推荐