定義對象間一種一對多的依賴關係,使得每當一個對象改變狀態,則因此依賴於它的對象都會獲得通知並被自動更新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