Android技术知识Android开发Android开发经验谈

RecycleView 的刷新流程

2018-06-07  本文已影响46人  糖葫芦_倩倩

梳理RecycleView的刷新流程,从入口开始

mAdapter.notifyDataSetChanged();//全部刷新

跟着源码 走,看到这个:

public final void notifyDataSetChanged() {
            mObservable.notifyChanged();
}

mObservable 字面上就是 被观察者嘛,被观察者调用 notifyChanged() 方法,然后我们继续跟:
notifyChanged() 方法如下:

public void notifyChanged() {
            // since onChanged() is implemented by the app, it could do anything, including
            // removing itself from {@link mObservers} - and that could cause problems if
            // an iterator is used on the ArrayList {@link mObservers}.
            // to avoid such problems, just march thru the list in the reverse order.
            for (int i = mObservers.size() - 1; i >= 0; i--) {
                mObservers.get(i).onChanged();
            }
        }

于是就到了上面,大概意思就是,循环遍历所有的 mObservers 观察者,观察者调用自身的 onChanged() 方法进行刷新数据。
那么onChanged() 又是什么呢?

public abstract static class AdapterDataObserver {
        public void onChanged() {
            // Do nothing
        }
}

是一个抽象类,实现类是:

private class RecyclerViewDataObserver extends AdapterDataObserver {
        RecyclerViewDataObserver() {
        }

        @Override
        public void onChanged() {
            //Checks if RecyclerView is in the middle of a layout or scroll and throws an IllegalStateException
            //检查 recycleView 是否正在滑动 如果是则抛出这个异常
            assertNotInLayoutOrScroll(null);
            
            mState.mStructureChanged = true;
            //循环遍历给每个item addFlags
            setDataSetChangedAfterLayout();
            if (!mAdapterHelper.hasPendingUpdates()) {
                //最后调用requestLayout
                requestLayout();
            }
        }
}

RecycleViewDataObserver 最终实现 onChanged() 方法,在最后调用的 requestLayout() 方法,触发 onMeasure() 方法,onMeasure() 方法中最终 会调用 onLayoutChildren(mRecycler, mState) 方法,而具体的实现是在它设置 LayoutManager 中,因为每个layoutmanager 具体测量child 规则不同,拿这个 LinearLayoutManager 中举例:

@Override
    public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
    xxx篇幅很长
    fill(recycler, mLayoutState, state, false);
    }

会调用其中的 fill() -> layoutChunk() -> next(recycler) -> recycler.getViewForPosition(mCurrentPosition) -> tryGetViewHolderForPositionByDeadline(position, dryRun, FOREVER_NS).itemView -> tryBindViewHolderByDeadline(holder, offsetPosition, position, deadlineNs); -> mAdapter.bindViewHolder(holder, offsetPosition); 终于找完了....

出口-> 一直到最后调用到 onBindViewHolder(RecyclerView.ViewHolder holder, int position) 刷新布局view 完成整个刷新流程 。

上一篇下一篇

猜你喜欢

热点阅读