定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则因此依赖于它的对象都会获得通知并被自动更新java
classDiagram Subject o.. Observer Subject <|-- ConcreteSubject Observer <|-- ConcreteObserver class Subject{ <<abstract>> +register(Observer) +unregister(Observer) +nofityObservers(Object) } class ConcreteSubject{ +nofityObservers(Object) } class Observer{ <<interface>> +update(Object) } class ConcreteObserver{ +update(Object) }
Android源码中有不少使用了观察者模式,好比OnClickListener、ContentObserver、 android.database.Observer 等。还有不少组件库Rxjava、RxAndroid、EventBus;这里咱们来看下经常使用的Adapter的notifyDataSetChanged()。android
public abstract class BaseAdapter implements ListAdapter,SpinnerAdapter {
//数据集观察者
private final DataSetObservable mDataSetObservable = new DataSetObservable();
public void registerDataSetObserver(DataSetObserver observer) {
mDataSetObservable.registerObserver(observer);
}
public void unregisterDataSetObserver(DataSetObserver observer) {
mDataSetObservable.unregisterObserver(observer);
}
/** * 当数据变化时,通知全部观察者 */
public void notifyDataSetChanged() {
mDataSetObservable.notifyChanged();
}
}
复制代码
这里能够看到BaseAdapter 里有一个DataSetObservable 的被观察者,经过register*()、unregister*()方法添加和删除观察者。咱们往下看DataSetObservable 这个类markdown
public class DataSetObservable extends Observable<DataSetObserver> {
/** * 当数据变化时调用每一个观察者的onChanged() 方法通知它们 */
public void notifyChanged() {
synchronized(mObservers) {
// 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();
}
}
}
}
复制代码
这里其实很简单,就是遍历全部观察者并调用它们的onChanged()。接下来咱们看是谁调用了BaseAdapter 的 registerDataSetObserver(DataSetObserver observer)方法。app
public void setAdapter(ListAdapter adapter) {
if (mAdapter != null && mDataSetObserver != null) {
mAdapter.unregisterDataSetObserver(mDataSetObserver);
}
//省略代码...
// AbsListView#setAdapter will update choice mode states.
super.setAdapter(adapter);
if (mAdapter != null) {
mAreAllItemsSelectable = mAdapter.areAllItemsEnabled();
mOldItemCount = mItemCount;
mItemCount = mAdapter.getCount();
checkFocus();
//建立一个数据集观察者
mDataSetObserver = new AdapterDataSetObserver();
//将这个观察者注册到 Adapter 的 DataSetObservable 中
mAdapter.registerDataSetObserver(mDataSetObserver);
//省略代码...
} else {
//省略代码...
}
requestLayout();
}
复制代码
以上能够看出ListVeiw 中有一个观察者(AdapterDataSetObserver)在setAdapter() 的时候注册到了Adapter 的DataSetObservable 中,当Adapter 调用 notifyDataSetChanged() 方法时就会通知 ListView 中的观察者(AdapterDataSetObserver)更新状态。异步
观察者模式主要的做用就是解耦,将观察者与被观察者彻底隔离,只依赖于 Observer 和 Observable 抽象,提供代码的灵活性和可扩展性。spa
优势: 观察者和被观察者直接是抽象耦合,应对业务变化。加强系统灵活性、可扩展性。code
缺点: 在应用观察者模式时须要考虑一下开发效率和运行效率问题,由于一个被观察者可能直接或间接有不少观察者,Java 消息中的通知默认顺序执行,通知到因此观察者可能须要花费些时间,若是一个观察者卡顿,会影响总体的执行效率,这里通常考虑采用异步的方式。orm