在閻宏博士的《JAVA與模式》一書中開頭是這樣描述觀察者(Observer)模式的:
觀察者模式是對象的行爲模式,又叫發佈-訂閱(Publish/Subscribe)模式、模型-視圖(Model/View)模式、源-監聽器(Source/Listener)模式或從屬者(Dependents)模式。
觀察者模式定義了一種一對多的依賴關係,讓多個觀察者對象同時監聽某一個主題對象。這個主題對象在狀態上發生變化時,會通知所有觀察者對象,使它們能夠自動更新自己。
觀察者模式的結構
一個軟件系統裏面包含了各種對象,就像一片欣欣向榮的森林充滿了各種生物一樣。在一片森林中,各種生物彼此依賴和約束,形成一個個生物鏈。一種生物的狀態變化會造成其他一些生物的相應行動,每一個生物都處於別的生物的互動之中。
registerForCallStateChanged中new了一個Registrant觀察者,將其加入到通知者中,來看Registrant是怎麼存儲的?
當不需要監聽時,可註銷:
2、mCallStateRegistrants是怎麼通知GsmCallTracker CallState變化了?
在手機中,當通話狀態發生改變,Modem會向上傳遞消息,傳到framework時,被RIL.java接收處理:
mCallStateRegistrants使用notifyRegistrants來通知它的所有觀察者:
registrants就是之前存儲所有觀察者的ArrayList,遍歷,通知。
Android Telephony源碼中用到了大量的觀察者模式,理解觀察者模式,有助於我們閱讀源碼。
觀察者模式是對象的行爲模式,又叫發佈-訂閱(Publish/Subscribe)模式、模型-視圖(Model/View)模式、源-監聽器(Source/Listener)模式或從屬者(Dependents)模式。
觀察者模式定義了一種一對多的依賴關係,讓多個觀察者對象同時監聽某一個主題對象。這個主題對象在狀態上發生變化時,會通知所有觀察者對象,使它們能夠自動更新自己。
觀察者模式的結構
一個軟件系統裏面包含了各種對象,就像一片欣欣向榮的森林充滿了各種生物一樣。在一片森林中,各種生物彼此依賴和約束,形成一個個生物鏈。一種生物的狀態變化會造成其他一些生物的相應行動,每一個生物都處於別的生物的互動之中。
同樣,一個軟件系統常常要求在某一個對象的狀態發生變化的時候,某些其他的對象做出相應的改變。做到這一點的設計方案有很多,但是爲了使系統能夠易於複用,應該選擇低耦合度的設計方案。減少對象之間的耦合有利於系統的複用,但是同時設計師需要使這些低耦合度的對象之間能夠維持行動的協調一致,保證高度的協作。觀察者模式是滿足這一要求的各種設計方案中最重要的一種。(上文源於網絡)
上圖是觀察者模式的基本模型,以通話狀態(CallState)爲例,來分析手機通話狀態變化時,是怎麼傳遞這個事件的。
RegistrantList作爲通知者,Registrant爲觀察者,RegistrantList通知者提供了add、remove、notifyRegistrants來管理Registrant。
1、通話狀態是怎麼被監聽的?
mCallStateRegistrants是RegistrantList的一個對象,在BaseCommand.java中生成,並對RegistrantList通知者的添加、刪除做了封裝:
protected RegistrantList mCallStateRegistrants = new RegistrantList();
public void registerForCallStateChanged(Handler h, int what, Object obj) {
Registrant r = new Registrant (h, what, obj);//觀察者
mCallStateRegistrants.add(r);
}
public void unregisterForCallStateChanged(Handler h) {
mCallStateRegistrants.remove(h);
}
registerForCallStateChanged中new了一個Registrant觀察者,將其加入到通知者中,來看Registrant是怎麼存儲的?
public synchronized void
add(Registrant r)
{
removeCleared();
registrants.add(r);
}
registrants是一個 ArrayList對象,管理Registrant其實就是對 ArrayList的操作。
registerForCallStateChanged是在GsmCallTracker.java的構造函數被調用的:
mCi.registerForCallStateChanged(this, EVENT_CALL_STATE_CHANGE, null);
this就是GsmCallTracker本身,GsmCallTracker繼承了Handler,此處,也就是說GsmCallTracker成爲了觀察者,當CallState變化時mCallStateRegistrants應該通知GsmCallTracker。當不需要監聽時,可註銷:
mCi.unregisterForCallStateChanged(this);
2、mCallStateRegistrants是怎麼通知GsmCallTracker CallState變化了?
在手機中,當通話狀態發生改變,Modem會向上傳遞消息,傳到framework時,被RIL.java接收處理:
case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED:
if (RILJ_LOGD) unsljLog(response);
mCallStateRegistrants
.notifyRegistrants(new AsyncResult(null, null, null));
break;
mCallStateRegistrants使用notifyRegistrants來通知它的所有觀察者:
public /*synchronized*/ void
notifyResult(Object result)
{
internalNotifyRegistrants (result, null);
}
private synchronized void
internalNotifyRegistrants (Object result, Throwable exception)
{
for (int i = 0, s = registrants.size(); i < s ; i++) {
Registrant r = (Registrant) registrants.get(i);
r.internalNotifyRegistrant(result, exception);
}
}
registrants就是之前存儲所有觀察者的ArrayList,遍歷,通知。
3、觀察者Registrant是怎麼響應處理通知的?
上面看到r.internalNotifyRegistrant(result, exception),觀察者知道callstate發生變化後,誰來真正處理?
Registrant部分代碼:
internalNotifyRegistrant (Object result, Throwable exception)
{
Handler h = getHandler();
if (h == null) {
clear();
/// M: Registrant Debug Log Enhancement
Log.d("Registrant", "internalNotifyRegistrant(): Warning! Handler is null, it could be already GCed. ( what=" + what + ", userObj=" + userObj + ", result=" + result + ", exception=" + exception + " )");
} else {
Message msg = Message.obtain();
msg.what = what;
msg.obj = new AsyncResult(userObj, result, exception);
h.sendMessage(msg);
}
}
Handler h = getHandler();獲得的Handler就是上文說到的this,也就是GsmCallTracker,what就是registerForCallStateChanged註冊時的第二個參數EVENT_CALL_STATE_CHANGE,這裏h.sendMessage也就是用的GsmCallTracker這個Handler發送的消息。我們都知道,Handler發送的消息都會被它自己的handleMessage()方法所接收處理。
於是,我們在GsmCallTracker的handleMessage()方法中看到:
case EVENT_CALL_STATE_CHANGE:
pollCallsWhenSafe();
break;
具體做什麼操作,我們就不管了。。。Android Telephony源碼中用到了大量的觀察者模式,理解觀察者模式,有助於我們閱讀源碼。
未完待續,有不對的地方,請指正。