RecyclerView数据更新通知——观察者模式

目录

观察者模式

RecyclerView数据更新

通知模式

观察者实现类

总结


最近在写毕业设计,遇到了要更新RecyclerView展示的数据。于是看了一下源码顺带加深对观察者模式的理解。

观察者模式

观察者模式定义如下:

观察者模式:定义对象之间的一种一对多的依赖关系,使得每当一个对象状态发生改变时其相关依赖对象皆得到通知并自动更新

Observer Pattern: Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.

摘自《Java设计模式》

举一个生活中简单的例子:

当红绿灯变成红灯时,汽车需要停下来,此时行人可以过马路;当红绿灯变绿灯时,行人需要停下来等待,汽车可以通行。

这就是一个典型的观察者模式,在这个例子中,红绿灯是被观察者,而行人和汽车属于观察者

当红绿灯发生变化时,行人和汽车都接收到通知,然后做出反应。这就是观察者模式。

如果觉得观察者和被观察者的概念比较难理解,那么可以理解为被观察者是首先改变并发起通知的对象,而观察者是接受到通知做出相应反应的对象

RecyclerView数据更新

通知模式

RecyclerView把数据持有交给了Adapter去处理。我们要更新数据也是调用Adapter的方法去更新。

Adapter提供了以下的方法:

// 更改整个数据
public final void notifyDataSetChanged()   
// 更改position位置的item
public final void notifyItemChanged(int position)
// 从positionStart位置开始更改itemCount个item
public final void notifyItemRangeChanged(int positionStart, int itemCount)
// 在position位置插入一个item
public final void notifyItemInserted(int position)
// 把fromPosition位置上的item移动到toPosition位置上
public final void notifyItemMoved(int fromPosition, int toPosition)
// 在position位置插入itemCount个item
public final void notifyItemRangeInserted(int positionStart, int itemCount)
// 移除position位置上的item
public final void notifyItemRemoved(int position)
// 从positionStart位置开始移除itemCount个item
public final void notifyItemRangeRemoved(int positionStart, int itemCount)

这里本文以notifyDataSetChanged()为例,探索一下RecyclerView数据更新是怎么使用观察者模式的。

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

进入这个函数,发现里面就一句话。再点进去

static class AdapterDataObservable extends Observable<AdapterDataObserver> {
       ...
​
        public void notifyChanged() {
            for (int i = mObservers.size() - 1; i >= 0; i--) {
                mObservers.get(i).onChanged();
            }
        }
    ...
}

发现Adapter里有这样一个静态类AdapterDataObservable,继承自Observable.

这里的Observable是一个抽象类,可以理解为这是一个被观察者的类。这个类里有一个成员变量mObservers

protected final ArrayList<T> mObservers = new ArrayList<T>();

这个变量是用来保存观察者的。

Observable这个类只提供了三个方法:

// 注册某个观察者
public void registerObserver(T observer)
// 注销某个观察者
public void unregisterObserver(T observer)
// 注销所有观察者
public void unregisterAll()

所以AdapterDataObservable这个类是一个被观察者的身份。而notifyChanged()这个方法,就是用来通知观察者我现在调用了notifyDataSetChanged()这个方法。

那么观察者就是AdapterDataObserver这个类了。

点进去发现这个类也是一个抽象类,定义了要实现的方法,但没有具体实现。我们会发现这些方法和Adapter里的方法能够一一对应起来。

    public abstract static class AdapterDataObserver {
        public void onChanged() {
            // Do nothing
        }
​
        public void onItemRangeChanged(int positionStart, int itemCount) {
            // do nothing
        }
​
        public void onItemRangeChanged(int positionStart, int itemCount, @Nullable Object payload) {
            // fallback to onItemRangeChanged(positionStart, itemCount) if app
            // does not override this method.
            onItemRangeChanged(positionStart, itemCount);
        }
​
        public void onItemRangeInserted(int positionStart, int itemCount) {
            // do nothing
        }
​
        public void onItemRangeRemoved(int positionStart, int itemCount) {
            // do nothing
        }
​
        public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {
            // do nothing
        }
    }

配合下面这张图能够更好地理解。

观察者实现类

但是,具体实现的观察类在哪里呢?又是在哪里进行注册绑定的呢?

我们设置adapter的方式是通过

recyclerView.setAdapter(adapter)

进入这个函数看一看。

public void setAdapter(@Nullable Adapter adapter) {
        // bail out if layout is frozen
        setLayoutFrozen(false);
        setAdapterInternal(adapter, false, true);
        processDataSetCompletelyChanged(false);
        requestLayout();
    }

里面调用了setAdapterInternal(adapter, false, true),再进去看一看

private void setAdapterInternal(@Nullable Adapter adapter, boolean compatibleWithPrevious,
        boolean removeAndRecycleViews) {
    if (mAdapter != null) {
        mAdapter.unregisterAdapterDataObserver(mObserver);
        mAdapter.onDetachedFromRecyclerView(this);
    }
    ...
    mAdapterHelper.reset();
    final Adapter oldAdapter = mAdapter;
    mAdapter = adapter;
    if (adapter != null) {
        adapter.registerAdapterDataObserver(mObserver);
        adapter.onAttachedToRecyclerView(this);
    }
    ...
    mRecycler.onAdapterChanged(oldAdapter, mAdapter, compatibleWithPrevious);
    ...
}

通过源码可以看到,给RecycerlView设置新的Adapter的时候,会先在原来的Adapter(如果有)那里注销掉mObserver,然后再注册到新的Adapter。

也就是说在设置Adapter的时候,就已经进行了观察者模式的绑定注册。这里的mObserver就是我们要找的观察者的实现类。

private final RecyclerViewDataObserver mObserver = new RecyclerViewDataObserver();

private class RecyclerViewDataObserver extends AdapterDataObserver {
        RecyclerViewDataObserver() {
        }
​
        @Override
        public void onChanged() {
            assertNotInLayoutOrScroll(null);
            mState.mStructureChanged = true;
​
            processDataSetCompletelyChanged(true);
            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();
            }
        }
    }

RecyclerViewDataObserver就是观察者的实现类了,里面实现了所有对应的函数。

那现在我们的思路就很清晰了,RecyclerView数据更新的通知就是这样一个顺序。

  1. RecycerView绑定Adapter的时候,将自己的观察者实现类RecyclerViewDataObserver和Adapter的被观察者AdapterDataObservable绑定注册。

  2. 当Adapter发起数据更新的通知,就会通过AdapterDataObservable去通知所有注册绑定的RecyclerViewDataObserver。

  3. RecyclerViewDataObserver里再根据通知自己做出调整。

总结

本文以分析RecyclerView数据更新通知原理,加深了对观察者模式的理解。

猜你喜欢

转载自blog.csdn.net/qq_43478882/article/details/123280182
今日推荐