Android Telephony分析(二) ---- RegistrantList详解
前言
本文主要講解RegistrantList的原理,以及如何快速分析RegistrantList相關的代碼流程。?
在Telephony模塊中,在RIL、Tracker(ServiceStateTracker、CallTracker、DcTracker)、Phone(PhoneBase及其子類)、UICC框架、CallManager等等中都大量使用到的RegistrantList,可見RegistrantList使用范圍之廣。如果代碼流程中使用了RegistrantList,如何分析下一步代碼流程走到哪里也是必須掌握的技能。
1. RegistrantList的原理
在講解RegistrantList之前,先引出觀察者模式的概念:
觀察者模式:定義對象間的一種一(Subject)對多(Observer)的依賴關系,當一個對象的狀態發生改變時,所有依賴于它的對象都得到通知并且自動更新。
RegistrantList跟觀察者模式有點類似,先創建一個RegistrantList集合,專門關注某種消息;如果有人也對該消息感興趣的話,那么為他封裝一個Registrant對象并且添加到RegistrantList中;當有消息上報時,先通知RegistrantList,接著所有注冊到RegistrantList中的Registrant都會被通知到并且更新。
RegistrantList與Registrant的關系如下:?
RegistrantList中有:?
add()/addUnique()方法,用于增加一個Registrant;?
remove()方法,用于刪除一個Registrant;?
internalNotifyRegistrants()方法,用于通知所有的Registrant。
而Registrant中有:?
internalNotifyRegistrants()方法,用于在收到RegistrantList的通知之后,再更新自己的內容。
本文來自http://blog.csdn.net/linyongan?,轉載請務必注明出處。
2. RegistrantList的使用
我們在上一篇文章《Android Telephony分析(一) —- Phone詳解 》中曾經說到Phone接口中有大量的register/unregister的方法,為了跟上一篇文章相呼應,那么我們就選PhoneBase.java中監聽通話掛斷的mDisconnectRegistrants作為例子分析一下吧。?
(時序圖中的編號對應下面代碼注釋中的編號)
2.1 創建RegistrantList
在PhoneBase初始化的時候,會創建mDisconnectRegistrants用于監聽通話掛斷這個事件。
//1.創建RegistrantList-->監聽通話掛斷protected final RegistrantList mDisconnectRegistrants= new RegistrantList();//對應地也會封裝好增加Registrant/刪除Registrant的方法,//然后提供register/unregister方法給外界調用,@Overridepublic void registerForDisconnect(Handler h, int what, Object obj) {checkCorrectThread(h);//3.增加一個RegistrantmDisconnectRegistrants.addUnique(h, what, obj);}@Overridepublic void unregisterForDisconnect(Handler h) {//根據Handler刪除RegistrantmDisconnectRegistrants.remove(h);}- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
在RegistrantList的內部:
public class RegistrantList {//用一個列表來存儲所有的Registrant。//有點好奇源碼中為什么不用泛型?:ArrayList<Registrant> registrants = new ArrayList<Registrant>(); ArrayList registrants = new ArrayList();// of Registrantpublic synchronized voidadd(Handler h, int what, Object obj){ //創建一個Registrantadd(new Registrant(h, what, obj));}public synchronized voidaddUnique(Handler h, int what, Object obj){// if the handler is already in the registrant list, remove itremove(h);//4.創建一個Registrantadd(new Registrant(h, what, obj)); }public synchronized voidadd(Registrant r){removeCleared();//5.把Registrant添加到registrants列表中registrants.add(r);}public synchronized voidremove(Handler h){//遍歷列表中的Registrantfor (int i = 0, s = registrants.size() ; i < s ; i++) {Registrant r = (Registrant) registrants.get(i);Handler rh;rh = r.getHandler();/* Clean up both the requested registrant and* any now-collected registrants*/if (rh == null || rh == h) {//清空Registrant的內容r.clear();}}removeCleared();}public synchronized voidremoveCleared(){for (int i = registrants.size() - 1; i >= 0 ; i--) {Registrant r = (Registrant) registrants.get(i);if (r.refH == null) {//移除Handler為空的Registrantregistrants.remove(i);}}}- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
2.2 注冊監聽某個消息
在TelephonyConnection.java中
//2.注冊監聽某個消息getPhone().registerForDisconnect(mHandler, MSG_DISCONNECT, null);private final Handler mHandler = new Handler() {@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case MSG_DISCONNECT://10.最終代碼流程會走到這里,對之前監聽的消息作進一步處理break;}}}- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
2.3 發送通知
當收到通話掛斷的消息后,先通知RegistrantList
/*package*/ voidnotifyDisconnect(Connection cn) {//6.開始通知所有注冊到mDisconnectRegistrants中的RegistrantmDisconnectRegistrants.notifyResult(cn);}- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
在RegistrantList的內部:
public /*synchronized*/ voidnotifyResult(Object result){internalNotifyRegistrants (result, null);}private synchronized voidinternalNotifyRegistrants (Object result, Throwable exception){ //7.遍歷registrants列表for (int i = 0, s = registrants.size(); i < s ; i++) {Registrant r = (Registrant) registrants.get(i);//8.通知Registrantr.internalNotifyRegistrant(result, exception);}}- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
來到Registrant里:
internalNotifyRegistrant (Object result, Throwable exception){ //得到Handler對象Handler h = getHandler();if (h == null) {clear();} else {Message msg = Message.obtain();msg.what = what;msg.obj = new AsyncResult(userObj, result, exception);//9.通過回調,給Handler發送Messageh.sendMessage(msg);}}- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
整個RegistrantList注冊Registrant,再到通知Registrant這個過程,也是利用了回調,可以留意時序圖中,步驟2~步驟10,折騰了半天,最后還是回到TelephonyConnection中去。?
回顧上面第二小節的代碼:?
TelephonyConnection對PhoneBase說,你幫我留意一下通話掛斷這個消息啊!?
PhoneBase說,什么時候有通話掛斷消息來我也不清楚啊,要不你留個聯系方式給我??
TelephonyConnection就傳遞了Handler和消息類型給PhoneBase,然后自己就去忙其他事了。?
PhoneBase通過RegistrantList,把TelephonyConnection的聯系方式(Handler和消息類型)傳遞給了Registrant。?
等到通話掛斷消息上報時,RegistrantList先通知Registrant,然后Registrant就給TelephonyConnection發消息。
3. 學以致用
代碼中使用了RegistrantList,如何快速分析下一步流程走到哪里??
這是一個回調的過程,所以核心就是在哪里注冊就在哪里處理,我們要找到調用register方法的地方。?
還是以第二小節的mDisconnectRegistrants為例,假如我們不知道第二小節的內容,我們分析到這里:
- 1
- 1
先搜索mDisconnectRegistrants,找到registerXXX的方法;
public void registerForDisconnect(Handler h, int what, Object obj) {checkCorrectThread(h);mDisconnectRegistrants.addUnique(h, what, obj);}- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
再搜索registerXXX方法,找到調用register方法的地方;
getPhone().registerForDisconnect(mHandler, MSG_DISCONNECT, null);- 1
- 1
最后搜索”MSG_DISCONNECT”,找到handleMessage()方法對MSG_DISCONNECT消息的處理,所以下一步代碼流程就應該是走這里了。
原文地址:http://blog.csdn.net/linyongan/article/details/52036225
總結
以上是生活随笔為你收集整理的Android Telephony分析(二) ---- RegistrantList详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android Service 形式分类
- 下一篇: Android Telephony分析(