觀察者設計模式--listView的源碼分析

觀察者設計模式:
定義一個對象間一種一對多的依賴關係,當一個對象改變狀態,則所有依賴他的對象都會得到通知並且自動更新
定義一種對象之間一對多的依賴關係, 當一個對象改變狀態,則依賴他的對象都會得到通知並且自動更新

角色介紹:
抽象主題: subject
抽象主題角色把所有的觀察者對象的引用保存在一個聚集裏  比如 ArrayList  ,每個主題都可以 有任意數量的觀察者,  抽象主題提供一個藉口, 可以增加或者刪除觀察者對象,抽象主題又叫抽象被觀察者對象 Observable

具體主題:ConcreteSubject
將有關狀態存入具體的觀察者對象;在具體主題內部發生改變的時候,給所有登記過的觀察者發送通知   具體主題角色又叫具體被觀察者


抽象觀察者:Observer
爲所有的具體觀察者定義一個接口,在得到主題的通知時更新自己,這個藉口叫做更新接口

具體觀察者:ConcreteObserver
存儲與主題的狀態自怡的狀態,具體的觀察者實現抽象   觀察者所要求的更新接口,以便使本身的狀態與主題的狀態相協調。

baseAdapter就是一個觀察者設計模式,
listView更新完數據,會調用一個方法,notifyDataSetChanged()

Observer      抽象觀察者
Observable  抽象被觀察者  也就是subject   抽象主題

BaseAdapter是一個觀察者模式:
源碼中:
public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter {
 
//DataSetObservable 就是一個數據集的 被觀察者
private final DataSetObservable mDataSetObservable = new DataSetObservable();
 
public boolean hasStableIds() {
return false;
}
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.
//數據集有變化的時候通知所有的觀察者
*/
public void notifyDataSetChanged() {
mDataSetObservable.notifyChanged();
}

mDataSetObservable.notifyChanged();進入到notifyChanged()
public class DataSetObservable extends Observable<DataSetObserver> {
public void notifyChanged() {
synchronized(mObservers) {
for (int i = mObservers.size() - 1; i >= 0; i--) {
mObservers.get(i).onChanged();
}
}
}

遍歷了所有的觀察者,並且調用他們的 onChange()方法


這些觀察者 哪來?

public void setAdapter(ListAdapter adapter) {
        //如果有adapter 先註銷該adapter對應的觀察者
if (mAdapter != null && mDataSetObserver != null) {
mAdapter.unregisterDataSetObserver(mDataSetObserver);
}
 
.....
super.setAdapter(adapter);
.....
if (mAdapter != null) {
mAreAllItemsSelectable = mAdapter.areAllItemsEnabled();
//獲取數據集的數量
mOldItemCount = mItemCount;
mItemCount = mAdapter.getCount();
checkFocus();
//創建一個數據集觀察者
mDataSetObserver = new AdapterDataSetObserver();
//將這個觀察者註冊到Adapter中 實際上是註冊到DataSetObserver中
mAdapter.registerDataSetObserver(mDataSetObserver);
設置adapter的時候,會構建一個AdapterDataSetObserver   ,然後將這個觀察者註冊到adapter中   這樣 觀察者和被觀察者都有了  一般數據集就放到了Adapter 中

數據集一般來自adapter中  比如:
public abstract class UserAdapter extends BaseAdapter {
// 數據集
protected List<String> mDataSet = new LinkedList<String>();
protected Context mContext = null;
 
public CommonAdapter(Context context, List<String> dataSet) {
this.mDataSet = dataSet;
this.mContext = context;
}
}

AdapterDataSetObserver   繼承DataSetObserver   
  
class AdapterDataSetObserver extends DataSetObserver {
 
private Parcelable mInstanceState = null;
// 上文有說道,調用Adapter的notifyDataSetChanged的時候會調用所有觀察者的onChanged方法,核心實現就在這裏
@Override
public void onChanged() {
mDataChanged = true;
mOldItemCount = mItemCount;
// 獲取Adapter中數據的數量
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;
}
}

當調用notifyDataChange這個函數的時候,這個函數會調用DataSetObservable 的notifyChange函數,  這個函數會調用所有觀察者(AdapterDataSetObserver)的onChange()方法




來源:http://blog.csdn.net/bboyfeiyu/article/details/44040533

發佈了27 篇原創文章 · 獲贊 33 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章