自定義滾輪系列---設計模式之觀察者模式

對於Adapter我相信大家都很熟悉,在使用ListView或者是GridView控件時,我們經常會用到Adapter,我們通常的做法是自定義一個Adapter繼承自BaseAdapter,然後調用ListView的setAdapter()方法,將數據與ListView綁定起來。但是我們對於Adapter又瞭解多少呢,我們是否知道它的實現原理呢。

今天我們要說的是Adapter中的觀察者模式,如果你想詳細瞭解觀察者模式,你可以參考這篇文章 設計模式學習筆記-觀察者模式

一、關於觀察者模式主要有以下幾點:

1、定義:觀察者模式(Observer Pattern)也叫發佈訂閱模式(Publish/subscribe),它是一個在項目中經常使用的模式,其定義如下:

Define a one-to-many dependency between objects so that when one object changes state,all its dependents are notified and updated automatically(定義對象間一種一對多的依賴關係,使得每當一個對象改變狀態,則所有依賴與他的對象都會得到通知並被自動更新)

2、觀察者模式的通用類圖:

3、觀察者模式的幾個角色名稱:

·Subject被觀察者:定義被觀察者必須實現的職責,他必須能夠動態的增加,取消觀察者。他一般是抽象類或者實現類,僅僅完成作爲被觀察者必須實現的職責:管理觀察者並通知被觀察者。

·Observer被觀察者:觀察者接受到消息之後,即進行update(更新方法)操作,對接收到的信息進行處理。

·ConcreteSubject具體的被觀察者:定義被觀察者自己業務邏輯,同時定義對哪些事件進行通知。

·ConcreteObserver具體的觀察者:每個觀察者的在接收到消息後的處理反應是不同的,各個反應者有自己的處理邏輯。

 4、觀察者模式的使用場景:

1、對一個對象狀態的更新,需要其他對象同步更新,而且其他對象的數量動態可變

2、對象僅需要將自己的更新通知給其他對象而不需要知道其他對象的細節

、觀察者模式在ListView和WheelView中的應用

1、我們先來看一下類圖:

2、關於上面類圖,我們可以發現:

[1]DataSetObserve是觀察者

[2]DataSetObservable是被觀察者,即角色,它持有很多個觀察者對象

[3]DataSetObservable持有DataSetObserve對象

[4]而BaseAdapter中又持有DataSetObservable對象,所以相當於,BaseAdapter也持有DataSetObserve對象
3、接着我們再看ListView中的setAdapter()方法

ListView的setAdapter()方法的源代碼我就不貼出來了,我們可以在setAdapter()方法中可以看到這樣一句mAdapter.registerDataSetObserver(mDataSetObserver);在BaseAdapter類中我們可以看到registerDataSetObserver()方法的具體實現爲:

public voidregisterDataSetObserver(DataSetObserver observer) {
mDataSetObservable.registerObserver(observer);
}
而該方法又是調用了DataSetObservable中的registerObserve(observer)方法,在DataSetObservable中我們可以看到registerObserve()方法的具體實現爲:
public voidregisterObserver(T observer) {
if(observer ==null) {
throw newIllegalArgumentException("The observer is null.");
}
synchronized(mObservers) {
if(mObservers.contains(observer)) {
throw newIllegalStateException("Observer "+ observer +" is already registered.");
}
mObservers.add(observer);
}
}
所以通過Listview的setAdapter方法,我們就將一個DataSetObserve添加到了Adapter的DataSetObservable中,即給adapter添加了一個觀察者
4、下面我們來看一下adapter中notifyDataSetChanged方法的實現過程
當數據有變動時,我們經常通過notifyDataSetChanged方法來刷新界面,在BaseAdapter類中,我們可以看到notifyDataSetChanged方法的具體實現爲:
public voidnotifyDataSetChanged() {
mDataSetObservable.notifyChanged();
}
我們又可以看到notifyDataSetChanged()方法中僅僅是調用了DataSetObservable中的notifyChanged()方法,接下來我們再來看notifyChanged方法的具體實現:
DataSetObservable類中
public voidnotifyChanged() {
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(inti =mObservers.size() - 1; i >= 0; i--) {
mObservers.get(i).onChanged();
}
}
}
我們可以看到,它的實現也很簡單,就是通過循環的方式,依次調用每個觀察者(DataSetObserver)的onChanged()方法;我們在ListView的setAdapter方法中調用的mAdapter.registerDataSetObserver(mDataSetObserver);方法中的參數mDataSetobserver是一個AdapterDataSetObserver 類型的類,而它又是繼承自DataSetObserver類的, 下面我們可以看到AdapterDataSetObserver 類的源碼實現:
class AdapterDataSetObserver extends DataSetObserver
{
private Parcelable mInstanceState = null;
AdapterDataSetObserver() {
}
public void onChanged() { mDataChanged = true;
mOldItemCount = mItemCount;
mItemCount = getAdapter().getCount();
if ((getAdapter().hasStableIds()) && (mInstanceState != null) && (mOldItemCount == 0) && (mItemCount > 0))
{
onRestoreInstanceState(mInstanceState);
mInstanceState = null;
} else {
rememberSyncState();
}
checkFocus();
requestLayout();
}
//...省略不必要代碼
}
在該類中我們可以看到調用了requestLayout()方法,該方法就是用來進行頁面刷新的
自定義滾輪中AbstractWheelAdapter的實現方式與Android中BaseAdapter的實現方式類似,它也使用了觀察者模式,只是他沒有使用一個單獨的被觀察者角色(類似於Android源碼中的DataSetObservable類),而是讓AbstractWheelAdapter直接持有觀察者對象,即AbstractWheelAdapter本身就是一個被觀察者,它裏面有一個datasetObservers變量用來存儲觀察者對象。
Android源碼的實現方式爲,adapter持有被觀察者,而被觀察者再持有觀察者對象。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章