观察者模式(Observer Design Pattern)也被称为发布订阅模式(Publish-Subscribe Design Pattern)
Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.
在对象之间定义一个一对多的依赖,当一个对象状态改变的时候,所有依赖的对象都会自动收到通知。
一般情况下,被依赖的对象叫作被观察者(Observable),依赖的对象叫作观察者(Observer)。
1 观察者模式 UML

- Subject:抽象主题,也就是被观察(Observable)的角色,抽象主题角色把所有观察者对象的引用保存在一个集合里,每个主题都可以有任意数量的观察者,抽象主题提供一个接口,可以增加和删除观察者对象。
- ConcreteSubject:具体主题,该角色将有关状态存入具体观察者对象,在具体主题的内部状态发生改变时,给所有注册过的观察者发出通知,具体主题角色又叫做具体被观察者(Concrete Observable)角色。
- Observer:抽象观察者,该角色是观察者的抽象类,它定义了一个更新接口,使得在得到主题的更改通知时更新自己。
- ConcreteObserver:具体的观察者,该角色实现抽象观察者角色所定义的更新接口,以便在主题的状态发生变化时更新自身的状态。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| public interface Subject { void registerObserver(Observer observer);
void removeObserver(Observer observer);
void notifyObservers(Message message); }
public class ConcreteSubject implements Subject { private List<Observer> observers = new ArrayList<>();
@Override public void registerObserver(Observer observer) { observers.add(observer); }
@Override public void removeObserver(Observer observer) { observers.remove(observer); }
@Override public void notifyObservers(Message message) { for (Observer observer : observers) { observer.update(message); } } }
public interface Observer { void update(Message message); }
public class ConcreteObserverOne implements Observer { @Override public void update(Message message) { System.out.println("ConcreteObserverOne is notified."); } }
public class ConcreteObserverTwo implements Observer { @Override public void update(Message message) { System.out.println("ConcreteObserverTwo is notified."); } }
ConcreteSubject subject = new ConcreteSubject(); subject.registerObserver(new ConcreteObserverOne()); subject.registerObserver(new ConcreteObserverTwo()); subject.notifyObservers(new Message());
|
2 Android 源码分析 notifyDataSetChanged
这次分析的是 Adapter 的 notifyDataSetChanged ,最终调用的是 RecyclerView.Adapter 的 notifyDataSetChanged 如下:
1 2 3
| public final void notifyDataSetChanged() { mObservable.notifyChanged(); }
|
这里的 mObservable 是 AdapterDataObservable 进入到 norifyChanged() 方法中。
1 2 3 4 5 6 7 8
| static class AdapterDataObservable extends Observable<AdapterDataObserver> { public void notifyChanged() { for (int i = mObservers.size() - 1; i >= 0; i--) { mObservers.get(i).onChanged(); } }
|
这里遍历了所有的观察者,并且调用它们的 onChanged 方法。这里的 mObservers 是父类中的一个 ArrayList<T> ,并且有一个 register 方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| 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); } }
|
RecyclerView 中调用 registerObserver 的地方是 RecyclerView.Adapter 的 registerAdapterDataObserver
1 2 3
| public void registerAdapterDataObserver(@NonNull AdapterDataObserver observer) { mObservable.registerObserver(observer); }
|
这是在 setAdapter 中的 setAdapterInternal 中调用的
1 2 3 4 5 6 7 8 9 10 11
| private final RecyclerViewDataObserver mObserver = new RecyclerViewDataObserver();
private void setAdapterInternal(@Nullable Adapter adapter, boolean compatibleWithPrevious, boolean removeAndRecycleViews) { if (adapter != null) { adapter.registerAdapterDataObserver(mObserver); adapter.onAttachedToRecyclerView(this); } }
|
这里的 mObserver 是 RecyclerViewDataObserver ,然后查看 RecyclerViewDataObserver 中的 onChanged 方法,这就是之前遍历的实现方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| private class RecyclerViewDataObserver extends AdapterDataObserver { RecyclerViewDataObserver() { }
@Override public void onChanged() { assertNotInLayoutOrScroll(null); mState.mStructureChanged = true;
processDataSetCompletelyChanged(true); if (!mAdapterHelper.hasPendingUpdates()) { requestLayout(); } }
|
这里最终调用了 requestLayout 刷新了 RecyclerView 页面。这!就是一个观察者模式。
总结
- 首先
setAdapter 会将 RecyclerViewDataObserver 添加到注册列表 mObservers 中。
- 当我们在调用
norifyChanged() 方法的时候,循环注册列表中的 Observer 的 onChanged 方法,其实就是调用 RecyclerViewDataObserver 的 onChanged
onChanged 会获取新的数据并刷新 RecyclerView 重新布局。
3 Android 源码 Broadcast
Android Broadcast广播机制分析
感谢
设计模式之美
《Android 源码设计模式解析与实战》
以及上文中的链接