Android开发RecyclerView的适配器notifyDataSetChange做了什么?

Android开发RecyclerView的内容更新流程
RecyclerView是如何更新的呢?
我们调用一个notifiDateSetChange以后发生了什么事情呢?
我们从中可以学习到什么思想呢?
如何使用RecyclerView
- 创建/从布局中找到RecyclerView控件
- 创建布局管理器,设置布局管理器(很多刚学习的同学会忘记这个步骤)
- 创建适配器,设置适配器
- 给适配器设置数据
这里面有几个点: 1. RecyclerView 2. 布局管理器 3. 适配器 4. 数据
数据更新时,如何让UI更新呢?
数据改变,我们调用适配器里的notifyDateSetChange方法,UI更新
data --> adapter --> recyclerView
为什么RecyclerView不是调用RecyclerView.notifyDateSetChange呢?对吧!面向对象的思想。那如果说是因为数据在adapter里头,所以调用adapter.notifyDatesetChange也说得过去,那么,调用notifyDateSetChange以后,怎么会让RecyclerView更新呢?adapter不持有RecyclerView的引用呀,不是adapter.setRecyclerView(recyclerView)呀,对吧!
接下来我们就阅读一下源码,adapter跟recyclerView是如何通讯的!
源码分析
从适配器的notifyDataSetChange开始说起:
mTestAdapter.notifyDataSetChanged();
   public final void notifyDataSetChanged() {
            mObservable.notifyChanged();
        }
这就是adapter里头的notifyDataSetChanged方法,也就是说我们调用了notifyDataSetChanged以后,它就会调用mObservable里的notifyChanged方法。
好,路子来了!
mObservable,那么我们就关心这个东西是怎么来的,什么时候创建/或者设置进来的。
小技巧,搜索创建/赋值的地方,可以加多等号来搜索。

mObservable它也是属于适配器里的对吧!那我们下一步干嘛?当然是搜索它使用的地方看看情况。
小技巧:搜索调用的地方可以mObservable.来搜索,加个点:


主要是两类,个是设置/取消Observer,一类是更新的调用。
那我们就看看这里更新的调用了。因为我们更新就是调用这个方法的呀:
        public final void notifyDataSetChanged() {
            mObservable.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();
            }
        }
所以,实际的操作就是遍历集合里的每一个Observer,然后调用其对应的方法,也就是说,重点在注册的地方:
  public void registerAdapterDataObserver(AdapterDataObserver observer) {
            mObservable.registerObserver(observer);
        }
那在哪里注册的呢?

其实两个都一样的,只是我这里一个是sdk里的,一个是support包里的:
点击跳转以后:

继续往前走:

到这里,我们就知道了。原来如此!
当我们给RecyclerView设置适配器的 时候,ReyclclerView反给adapter设置一个Observer
private final RecyclerViewDataObserver mObserver = new RecyclerViewDataObserver();
这个类的具体
private class RecyclerViewDataObserver extends AdapterDataObserver {
        RecyclerViewDataObserver() {
        }
        @Override
        public void onChanged() {
            assertNotInLayoutOrScroll(null);
            mState.mStructureChanged = true;
            setDataSetChangedAfterLayout();
            if (!mAdapterHelper.hasPendingUpdates()) {
                requestLayout();
            }
        }
        @Override
        public void onItemRangeChanged(int positionStart, int itemCount, Object payload) {
            assertNotInLayoutOrScroll(null);
            if (mAdapterHelper.onItemRangeChanged(positionStart, itemCount, payload)) {
                triggerUpdateProcessor();
            }
        }
        @Override
        public void onItemRangeInserted(int positionStart, int itemCount) {
            assertNotInLayoutOrScroll(null);
            if (mAdapterHelper.onItemRangeInserted(positionStart, itemCount)) {
                triggerUpdateProcessor();
            }
        }
        @Override
        public void onItemRangeRemoved(int positionStart, int itemCount) {
            assertNotInLayoutOrScroll(null);
            if (mAdapterHelper.onItemRangeRemoved(positionStart, itemCount)) {
                triggerUpdateProcessor();
            }
        }
        @Override
        public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {
            assertNotInLayoutOrScroll(null);
            if (mAdapterHelper.onItemRangeMoved(fromPosition, toPosition, itemCount)) {
                triggerUpdateProcessor();
            }
        }
        void triggerUpdateProcessor() {
            if (POST_UPDATES_ON_ANIMATION && mHasFixedSize && mIsAttached) {
                ViewCompat.postOnAnimation(RecyclerView.this, mUpdateChildViewsRunnable);
            } else {
                mAdapterUpdateDuringMeasure = true;
                requestLayout();
            }
        }
    }
所以,当我们调用notifyDatesetChange的时候,就调用RecyclerView设置过来Observer里的onChange方法
    @Override
        public void onChanged() {
            assertNotInLayoutOrScroll(null);
            mState.mStructureChanged = true;
            setDataSetChangedAfterLayout();
            if (!mAdapterHelper.hasPendingUpdates()) {
                requestLayout();
            }
        }
而onChange方法则调用requireLayout,请求重新布局。这时,就会重新从适配器里载布局了。
好啦!欢迎大家也分享自己阅读源码的记录。




























