Android——RecyclerView下的观察者模式

来源:互联网 发布:中国未来 通胀 知乎 编辑:程序博客网 时间:2024/05/18 02:12

首先看一下Observable这个类

public abstract class Observable<T> {      protected final ArrayList<T> mObservers = new ArrayList<T>();       public void registerObserver(T observer) {        if (observer == null) {            throw new IllegalArgumentException("The observer is null.");        }        synchronized(mObservers) {            if (mObservers.contains(observer)) {                throw new IllegalStateException("Observer " + observer + " is already registered.");            }            mObservers.add(observer);        }    }        public void unregisterObserver(T observer) {        if (observer == null) {            throw new IllegalArgumentException("The observer is null.");        }        synchronized(mObservers) {            int index = mObservers.indexOf(observer);            if (index == -1) {                throw new IllegalStateException("Observer " + observer + " was not registered.");            }            mObservers.remove(index);        }    }       public void unregisterAll() {        synchronized(mObservers) {            mObservers.clear();        }    }}

这是被观察者的类。上面的泛型接收一个观察者的参数。


再看一下RecyclerView自己定义的观察者类

public static abstract class AdapterDataObserver {    public void onChanged() {        // Do nothing    }    public void onItemRangeChanged(int positionStart, int itemCount) {        // do nothing    }    public void onItemRangeChanged(int positionStart, int itemCount, 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    }}
其实正常情况下应该是定义一个观察者类,然后实现Observer这个接口的。但是他可能想降低耦合度,所以干脆没有实现这个接口。


观察者和被观察者都已经具备了。(其实他们到现在为止,都还只是模板而已)


现在看一下被观察者的实现类

static class AdapterDataObservable extends Observable<AdapterDataObserver> {    public boolean hasObservers() {        return !mObservers.isEmpty();    }    public void notifyChanged() {                for (int i = mObservers.size() - 1; i >= 0; i--) {            mObservers.get(i).onChanged();        }    }    public void notifyItemRangeChanged(int positionStart, int itemCount) {        notifyItemRangeChanged(positionStart, itemCount, null);    }    public void notifyItemRangeChanged(int positionStart, int itemCount, Object payload) {                for (int i = mObservers.size() - 1; i >= 0; i--) {            mObservers.get(i).onItemRangeChanged(positionStart, itemCount, payload);        }    }    public void notifyItemRangeInserted(int positionStart, int itemCount) {               for (int i = mObservers.size() - 1; i >= 0; i--) {            mObservers.get(i).onItemRangeInserted(positionStart, itemCount);        }    }    public void notifyItemRangeRemoved(int positionStart, int itemCount) {                for (int i = mObservers.size() - 1; i >= 0; i--) {            mObservers.get(i).onItemRangeRemoved(positionStart, itemCount);        }    }    public void notifyItemMoved(int fromPosition, int toPosition) {        for (int i = mObservers.size() - 1; i >= 0; i--) {            mObservers.get(i).onItemRangeMoved(fromPosition, toPosition, 1);        }    }}
这就是被观察者的最终版本了,有没有似曾相识的感觉。这些都是在使用RecyclerView中用得到的方法,只是他这里的实现可能和各位看官的想法不太一样。他是通过取得父类中已经注册的观察者,然后调用观察者里的方法,这才实现了一个观察的过程!


最后看一下观察者的最终版本

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();        }    }}

我们梳理一下流程:

我们正常修改了RecyclerView中的数据集合后

1.mAdapter.notifyItemChanged(int position);

2.会转到RecyclerView中的这个方法,调用被观察者的方法

其实上面用户的这个notify就是相当于一个信号,告诉观察者某某处需要变化了!然后调用观察者的方法。

public final void notifyItemChanged(int position) {    mObservable.notifyItemRangeChanged(position, 1);}

private final AdapterDataObservable mObservable = new AdapterDataObservable();

3.转到被观察者的这个方法中

public void notifyChanged() {        for (int i = mObservers.size() - 1; i >= 0; i--) {        mObservers.get(i).onChanged();    }}
4.被观察者从ArrayList中取得已经注册的观察者,并调用他们的方法

public void onChanged() {    // Do nothing}
当然注册的肯定是子的观察者,调用的也应该是子的观察者里重写的方法

@Overridepublic void onChanged() {    assertNotInLayoutOrScroll(null);    mState.mStructureChanged = true;    setDataSetChangedAfterLayout();    if (!mAdapterHelper.hasPendingUpdates()) {        requestLayout();    }}

所以这个观察者模式就是接受到信息,改变被观察者状态,观察者接收到这个状态的变化(这两句话等同于:调用被观察者方法,转而调用所有观察者的方法)。通过这样一种规定的方法来观察,可以有效降低我们代码的耦合度,减少我们的代码量,提升代码的可重用性。

原创粉丝点击