觀察者模式
定義
定義對象間的一種一對多的依賴關系友酱,當一個對象的狀態(tài)發(fā)生改變時驳庭,所有依賴于它的對象都得到通知并被自動更新刑顺。
應用場景
有一個事件發(fā)生改變,需要通知其他多個對象時.更多的應用于異步回調(diào)場景.
代碼實現(xiàn)
UML類圖結(jié)構(gòu)
代碼實踐
1.Subject主題
public class Subject {
/**
* 事件持有觀察者的集合
*/
private List<Observer> observers=new ArrayList<>();
/**
* 事件的狀態(tài)
*/
private String state;
/**
* 增加觀察者
*/
public void attach(Observer observer){
observers.add(observer);
}
/**
* 遍歷通知觀察者
*/
public void notifyAllObservers(){
for (Observer observer : observers) {
observer.update(state);
}
}
public String getState() {
return state;
}
/**
* 當狀態(tài)發(fā)生改變,通知觀察者
*/
public void setState(String state) {
this.state = state;
notifyAllObservers();
}
}
2.觀察者接口
public interface Observer {
/**
* 更新觀察者的狀態(tài)
*/
public void update(String state);
}
3.觀察者具體實現(xiàn)
public class Observer1 implements Observer {
@Override
public void update(String state) {
// TODO Auto-generated method stub
System.out.println("Observer1 update:"+state);
}
}
4.測試
public class Test {
public static void main(String[] args) {
//新建事件
Subject subject=new Subject();
//新建觀察者
Observer observer1=new Observer1();
Observer observer2=new Observer2();
//綁定觀察者
subject.attach(observer1);
subject.attach(observer2);
//更新事件狀態(tài)
subject.setState("我更新了");
}
}
5.測試結(jié)果
Observer1 update:我更新了
Observer2 update:我更新了
ListView中的觀察者模式
在adapter中有一個內(nèi)部類AdapterDataSetObserver,這個就是一個觀察者.
在listView.setadapter時候會初始觀察者.
在AdapterDataSetObserver的onChanged函數(shù)中會獲取Adapter中數(shù)據(jù)集的新數(shù)量氯窍,然后調(diào)用ListView的requestLayout()方法重新進行布局,更新用戶界面蹲堂。
源碼分析
BaseAdapter 中notifyDataSetChanged 調(diào)用的mDataSetObservable.notifyChanged();
public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter {
// 數(shù)據(jù)集觀察者,這里將觀察者放到一個類中集中管理
private final DataSetObservable mDataSetObservable = new DataSetObservable();
public void registerDataSetObserver(DataSetObserver observer) {
mDataSetObservable.registerObserver(observer);
}
public void unregisterDataSetObserver(DataSetObserver observer) {
mDataSetObservable.unregisterObserver(observer);
}
/**
* Notifies the attached observers that the underlying data has been changed
* and any View reflecting the data set should refresh itself.
* 當數(shù)據(jù)集用變化時通知所有觀察者
*/
public void notifyDataSetChanged() {
mDataSetObservable.notifyChanged();
}
}
在mDataSetObservable.notifyChanged()中遍歷所有觀察者狼讨,并且調(diào)用它們的onChanged方法。
public class DataSetObservable extends Observable<DataSetObserver> {
/**
* Invokes onChanged on each observer. Called when the data set being observed has
* changed, and which when read contains the new state of the data.
*/
public void notifyChanged() {
synchronized(mObservers) {
// 調(diào)用所有觀察者的onChanged方式
for (int i = mObservers.size() - 1; i >= 0; i--) {
mObservers.get(i).onChanged();
}
}
}
...
}
繼承自AbsListView的父類AdapterView的AdapterDataSetObserver,
class AdapterDataSetObserver extends DataSetObserver {
private Parcelable mInstanceState = null;
// 上文有說道柒竞,調(diào)用Adapter的notifyDataSetChanged的時候會調(diào)用所有觀察者的onChanged方法,核心實現(xiàn)就在這里
@Override
public void onChanged() {
mDataChanged = true;
mOldItemCount = mItemCount;
// 獲取Adapter中數(shù)據(jù)的數(shù)量
mItemCount = getAdapter().getCount();
// Detect the case where a cursor that was previously invalidated has
// been repopulated with new data.
if (AdapterView.this.getAdapter().hasStableIds() && mInstanceState != null
&& mOldItemCount == 0 && mItemCount > 0) {
AdapterView.this.onRestoreInstanceState(mInstanceState);
mInstanceState = null;
} else {
rememberSyncState();
}
checkFocus();
// 重新布局ListView政供、GridView等AdapterView組件
requestLayout();
}
...
public void clearSavedState() {
mInstanceState = null;
}
總結(jié)
所謂觀察者模式,就是
多個觀察者Observer
-->觀察attach
--> 目標Subject
的變化--->并通知刷新update