美文网首页
Android源码中的设计模式-观察者模式

Android源码中的设计模式-观察者模式

作者: 刺客的幻影 | 来源:发表于2018-11-27 17:39 被阅读0次

事件总线框架大家应该都用过不少,从最开始的otto到Eventbus,再到Rxbus,这些开源框架都应用到了一个经典的设计模式-观察者模式。使用中,最直观的体验就是不用再去写那些繁琐的回调代码,模块和业务之间的耦合度也会极大程度地降低。

其实在Android源码中,观察者模式的使用无处不在,应用最广泛、典型的要数ListView和RecyclerView中的Adapter了。下面我们从RecyclerView.Adapter的源码中,分析它的观察者模式是如何实现的。

  • 首先从我们经常调用到的notifyDataSetChanged入手,这是一个通知数据改变,刷新界面布局的方法
public abstract static class Adapter<VH extends ViewHolder> {
        //被观察者
        private final AdapterDataObservable mObservable = new AdapterDataObservable();
        /**
         * 注册观察者,监听数据集的变化
         */
        public void registerAdapterDataObserver(AdapterDataObserver observer) {
            mObservable.registerObserver(observer);
        }

        /**
         * 取消注册,不再监听数据集的改变
         */
        public void unregisterAdapterDataObserver(AdapterDataObserver observer) {
            mObservable.unregisterObserver(observer);
        }

        /**
         * 通知注册的观察者数据集发生改变
         */
        public final void notifyDataSetChanged() {
            mObservable.notifyChanged();
        }
}
  • 实际调用的是AdapterDataObservable.notifyChanged()
static class AdapterDataObservable extends Observable<AdapterDataObserver> {

        public void notifyChanged() {
            //调用所有观察者的onChanged方法
            for (int i = mObservers.size() - 1; i >= 0; i--) {
                mObservers.get(i).onChanged();
            }
        }
}
  • 来到AdapterDataObserver中,调用其onChanged方法
 public abstract static class AdapterDataObserver {
        public void onChanged() {
            // Do nothing
        }
    }
  • 可以看到上面是一个抽象类,具体实现看其子类RecyclerViewDataObserver,这里就是观察者收到消息通知后的具体实现
private class RecyclerViewDataObserver extends AdapterDataObserver {
        //上面说到的所有观察者onChanged方法的核心实现
        @Override
        public void onChanged() {
            //确保RecyclerView没有在layout或者滑动状态
            assertNotInLayoutOrScroll(null);
            mState.mStructureChanged = true;
            //被观察者收到数据发生改变后的具体实现
            setDataSetChangedAfterLayout();
            if (!mAdapterHelper.hasPendingUpdates()) {
                //重新布局RecyclerView组件
                requestLayout();
            }
        }
}

其实到这一步观察者模式中事件的通知方式已经实现,想进一步探究是如何实现的可以继续深入,看看setDataSetChangedAfterLayout()方法

  • 那么问题来了,这里的观察者们是在哪里注册的呢?找到RecyclerView的setAdapter()方法
public class RecyclerView extends ViewGroup implements ScrollingView, NestedScrollingChild2 {
     public void setAdapter(Adapter adapter) {
        // bail out if layout is frozen
        setLayoutFrozen(false);
        //具体实现
        setAdapterInternal(adapter, false, true);
        requestLayout();
      }
  • 这里也只是包了一层,修改了状态,具体的实现看setAdapterInternal(adapter, false, true),注意关键点adapter.registerAdapterDataObserver(mObserver);
private void setAdapterInternal(Adapter adapter, boolean compatibleWithPrevious,
            boolean removeAndRecycleViews) {
        if (mAdapter != null) {
            //首先反注册掉所有观察者
            mAdapter.unregisterAdapterDataObserver(mObserver);
            mAdapter.onDetachedFromRecyclerView(this);
        }
        if (!compatibleWithPrevious || removeAndRecycleViews) {
            removeAndRecycleViews();
        }
        mAdapterHelper.reset();
        final Adapter oldAdapter = mAdapter;
        mAdapter = adapter;
        if (adapter != null) {
            //注册新的观察者
            adapter.registerAdapterDataObserver(mObserver);
            adapter.onAttachedToRecyclerView(this);
        }
        if (mLayout != null) {
            mLayout.onAdapterChanged(oldAdapter, mAdapter);
        }
        mRecycler.onAdapterChanged(oldAdapter, mAdapter, compatibleWithPrevious);
        mState.mStructureChanged = true;
        setDataSetChangedAfterLayout();
    }
  • 继续探究RecyclerView中registerAdapterDataObserver的具体实现
public class RecyclerView extends ViewGroup implements ScrollingView, NestedScrollingChild2 {
     public void registerAdapterDataObserver(AdapterDataObserver observer) {
            mObservable.registerObserver(observer);
     }
}
  • 看一下mObservable是什么
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的setAdapter的调用过程中被注册的。总的看来,观察者模式的实现原理是维护一个集合,添加或删除集合元素实现观察者的注册与反注册,遍历集合,调用元素的方法实现消息的推送

相关文章

网友评论

      本文标题:Android源码中的设计模式-观察者模式

      本文链接:https://www.haomeiwen.com/subject/ccojfqtx.html