當RIL收到這個訊息UNSOL_CALL_RING然後調用mRingRegistrant.notifyRegistrant(new AsyncResult (null, ret, null));mRingRegistrant是在哪裡註冊的呢?在BaseCommands.java通過這個方法註冊的: public void setOnCallRing(Handler h, int what, Object obj) { mRingRegistrant = new Registrant (h, what, obj); }setOnCallRing這個方法在phoneBase.java的建構函式種通過: mCM.setOnCallRing(this, EVENT_CALL_RING, null);ok,所以,此時,handleMessage處理EVENT_CALL_RING訊息,然後調用sendIncomingCallRingNotification()在這個方法裡面,做兩件事情: notifyIncomingRing(); sendMessageDelayed(obtainMessage(EVENT_CALL_RING_CONTINUE, token, 0), mCallRingDelay);後面的方法作用是用來迴圈播放鈴聲的。延遲多少秒具體各手機廠商不同。繼續:notifyIncomingRing()方法裡面主要是啟用這個註冊訊息: mIncomingRingRegistrants.notifyRegistrants(ar);ok,我們繼續看mIncomingRingRegistrants是在哪裡註冊的,可以看出是phoneBase.java註冊的 public void registerForIncomingRing( Handler h, int what, Object obj) { checkCorrectThread(h); mIncomingRingRegistrants.addUnique(h, what, obj); }checkCorrectThread這個方法主要是為了驗證當前的線程是不是和原來的線程保持一直,如果不是,拋出異常registerForIncomingRing這個方法是callManager.java註冊的 phone.registerForIncomingRing(mHandler, EVENT_INCOMING_RING, null);收到訊息後,然後處理EVENT_INCOMING_RING case EVENT_INCOMING_RING: if (!hasActiveFgCall()) { mIncomingRingRegistrants.notifyRegistrants((AsyncResult) msg.obj); } break;然後判斷當前有沒有前台call,如果有,停止處理,如果沒有,繼續....mIncomingRingRegistrants是在callManagar.java public void registerForIncomingRing(Handler h, int what, Object obj){ mIncomingRingRegistrants.addUnique(h, what, obj); }然後registerForIncomingRing是在phoneapp種的callNotifier.java中註冊: mCM.registerForIncomingRing(this, PHONE_INCOMING_RING, null);所以,最終到了phoneapp中的這裡,然後phoneApp處理PHONE_INCOMING_RING訊息,調用:mRinger.ring()完成響鈴和迴圈響鈴的工作;當然,來點的時候,這個訊息只是其中訊息的一個,僅僅是為了完成響鈴而來的訊息。下一步啟動phone的訊息,是一個叫UNSOL_RESPONSE_CALL_STATE_CHANGED 的訊息,處理機制和上面的一致,其實,FW層基本上都是這種套路,沒什麼特別。這個架構非常好,各層之間低耦合,很不錯。ok,其實上面說的都是廢話,這篇文章,其實我主要是想藉助這一個訊息,來說說RegistrantList這個類是如何來管理各種訊息之間的不斷添加和被啟用的。上面文章談到的那些mIncomingRingRegistrants都是RegistrantList.其實,說白了,這個RegistrantList就是Registrant的集合,字面意思Registrant是個什麼東東?哎,登記的意思,就是你要幹什麼活,先來人才中心登記下,等活來了,發現是你需要的,好,我通知你來幹活。Registrant本質上是個什麼東東?其實就是handle 和message的組合體。具體如下:首先我們看到RegistrantList裡面添加訊息方法:public synchronized void addUnique(Handler h, int what, Object obj) { // if the handler is already in the registrant list, remove it remove(h); add(new Registrant(h, what, obj)); }首先移除當前的handler,如果它存在當前的list中的話。然後把當前的訊息和handler添加到RegistrantList中去,RegistrantList是個ArrayList.對於這個add方法:public synchronized void add(Registrant r) { removeCleared(); // registrants.add(r); }上面的removeCleared()方法內容如下: public synchronized void removeCleared() { for (int i = registrants.size() - 1; i >= 0 ; i--) { Registrant r = (Registrant) registrants.get(i); if (r.refH == null) { registrants.remove(i); } } }可以看出其實這個方法就是移除ArrayList中的沒有指定的handler的Registrant的。r.refH 是一個java中的WeakRreference弱引用對象。什麼事弱引用呢?簡單點,就是可以儲存某對象的訊息,又不影響他的回收。好,繼續,上面的代碼先清除掉,然後添加到ArrayList中去儲存。ok, 在ril中mRingRegistrant.notifyRegistrant(new AsyncResult (null, ret, null));後,調用:public /*synchronized*/ void notifyRegistrants(AsyncResult ar) { internalNotifyRegistrants(ar.result, ar.exception); }然後 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); } }可以看出目前是在從ArrayList中取出所有的registrants,然後給觸發他們處理訊息。從這裡可以看出,我們可以為同一個ArrayList裡面添加幾個registrants,添加不同的what參數,然後在這裡都會被觸發啟用。回到上面方法的r.internalNotifyRegistrant(result, exception);/*package*/ void internalNotifyRegistrant (Object result, Throwable exception) { Handler h = getHandler(); if (h == null) { clear(); } else { Message msg = Message.obtain(); msg.what = what; msg.obj = new AsyncResult(userObj, result, exception); h.sendMessage(msg); } }其實,先不看這個方法,我們前面看到了,我們在add訊息的時候add(new Registrant(h, what, obj));是把訊息封裝成Registrant對象儲存起來了。看Registrant的構造方法:public Registrant(Handler h, int what, Object obj) { refH = new WeakReference(h); this.what = what; userObj = obj; }把當前的handler儲存到弱引用中,待會可以通過get()方法拿到。然後把訊息值等也儲存起來。然後,上面的方法internalNotifyRegistrant 中,我們可以看到第一步通過getHandler()方法獲得Handler對象public Handler getHandler() { if (refH == null) return null; return (Handler) refH.get(); //這裡大家看明白了吧,前面說了的。 }如果handler不存咋,調用clear方法清除。反之,通過訊息機制,發送訊息給這個訊息歸屬的handler處理,其實,就是前面的callNotifier.java並且帶上PLD返回來的AsyncResult訊息。Message msg = Message.obtain(); //一般獲得訊息都是通過這個方法,不是直接執行個體化,因為這個方法可以避免重複建立 msg.what = what; msg.obj = new AsyncResult(userObj, result, exception); h.sendMessage(msg);哎,都說到這裡了,順便說說android的handler機制吧首先,需要明白一些訊息機制的概念:Looper:一條線程可以產生一個looper對象,有他來管理此線程的messageQueue訊息佇列Handler:咱們可以構造Handler對象來與Looper溝通,以便push新訊息到MessageQueue裡面,或者接受Looper從訊息佇列裡面送出來的訊息。MessageQueue: 訊息佇列,用來存放線程中放入的訊息。線程:不講什麼UI線程了,網上很多,自己去看,普及下知識,什麼是線程?線程就是一段代碼邏輯從前到後的執行路徑,新開條線程,相當於有兩條路徑可以走ok,下面開始介紹android的handler和message機制ok,大家平常聽到的什麼UI線程,大家可以去看activity的源碼,在activity初始化的時候,就會有ActivityThread.java來建立主線程,在activity中建立looper和messageQueue對象等。這部分就不分析了,大家自己看看就行了。我分析的,僅限於當前的case首先h.sendMessage(msg);我們看這個方法:(當然,這個msg裡麵包含了pld返回的object還有我們訊息標誌的what資訊) /** * Pushes a message onto the end of the message queue after all pending messages * before the current time. It will be received in {@link #handleMessage}, * in the thread attached to this handler. * * @return Returns true if the message was successfully placed in to the * message queue. Returns false on failure, usually because the * looper processing the message queue is exiting. */ public final boolean sendMessage(Message msg) { return sendMessageDelayed(msg, 0); }繼續: public final boolean sendMessageDelayed(Message msg, long delayMillis) { if (delayMillis < 0) { //判斷小於0,不做處理 delayMillis = 0; } return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis); }繼續handler.java/** * Enqueue a message into the message queue after all pending messages * before the absolute time (in milliseconds) <var>uptimeMillis</var>. * <b>The time-base is {@link android.os.SystemClock#uptimeMillis}.</b> * You will receive it in {@link #handleMessage}, in the thread attached * to this handler. * * @param uptimeMillis The absolute time at which the message should be * delivered, using the * {@link android.os.SystemClock#uptimeMillis} time-base. * * @return Returns true if the message was successfully placed in to the * message queue. Returns false on failure, usually because the * looper processing the message queue is exiting. Note that a * result of true does not mean the message will be processed -- if * the looper is quit before the delivery time of the message * occurs then the message will be dropped. */ public boolean sendMessageAtTime(Message msg, long uptimeMillis) { boolean sent = false; MessageQueue queue = mQueue; //這個mQueue待會再說 if (queue != null) { //如果訊息佇列有,就把當前的handler對象給target,並把訊息給訊息佇列 msg.target = this; sent = queue.enqueueMessage(msg, uptimeMillis); } else { RuntimeException e = new RuntimeException( this + " sendMessageAtTime() called with no mQueue"); Log.w("Looper", e.getMessage(), e); } return sent; }前提咱們必須知道的是,一條線程最多隻有一個looper和一個messageQueue。這裡,我們要知道mQueue是從哪裡來的?其實,應該能猜到,肯定要構造傳進來啊看handler的構造方法: /** * Default constructor associates this handler with the queue for the * current thread. * * If there isn't one, this handler won't be able to receive messages. */ public Handler() { if (FIND_POTENTIAL_LEAKS) { final Class<? extends Handler> klass = getClass(); if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) && (klass.getModifiers() & Modifier.STATIC) == 0) { Log.w(TAG, "The following Handler class should be static or leaks might occur: " + klass.getCanonicalName()); } } mLooper = Looper.myLooper(); //獲得當前線程的looper對象 if (mLooper == null) { throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()"); } mQueue = mLooper.mQueue; //從looper對象中擷取它管理的messageQueue mCallback = null; }從looper物件建構方法可以看出:private Looper() { mQueue = new MessageQueue(); //執行個體化當前的messageQueue對象 mRun = true; mThread = Thread.currentThread(); //取得當前線程 }哈哈,懂了吧,最後看個方法,看訊息如何存到messageQueue中的 final boolean enqueueMessage(Message msg, long when) { if (msg.isInUse()) { throw new AndroidRuntimeException(msg + " This message is already in use."); } if (msg.target == null && !mQuitAllowed) { throw new RuntimeException("Main thread not allowed to quit"); } final boolean needWake; synchronized (this) { if (mQuiting) { RuntimeException e = new RuntimeException( msg.target + " sending message to a Handler on a dead thread"); Log.w("MessageQueue", e.getMessage(), e); return false; } else if (msg.target == null) { mQuiting = true; } msg.when = when; //Log.d("MessageQueue", "Enqueing: " + msg); Message p = mMessages; if (p == null || when == 0 || when < p.when) { msg.next = p; //好熟悉好熟悉啊,這個next肯定是message對象,百分之百,java實現鏈表資料結構就是這麼寫的啊,看來基礎真的很重要 mMessages = msg; needWake = mBlocked; // new head, might need to wake up } else { Message prev = null; while (p != null && p.when <= when) { prev = p; p = p.next; } msg.next = prev.next; prev.next = msg; needWake = false; // still waiting on head, no need to wake up } } if (needWake) { nativeWake(mPtr); } return true; }其實上面的方法就是把一個一個的message對象通過java鏈表的方式給串起來。ok,訊息已經放到訊息佇列裡面去了,那怎麼取出來?什麼時候取出來?如何取出來?取出來給誰?首先,我們要明白activity啟動的流程。簡單的說,是ActivityThread.java在做一系列的操作。每個應用程式都以ActivityThread.main()為入口進入到訊息迴圈處理。對於一個進程來講,我們需要這個閉合的處理架構。ActivitiyThread是應用程式概念空間的重要概念,他建立了應用進程啟動並執行架構,並提供了一個IActivityThread介面作為與 Activity Manager Service的通訊介面.通過該介面ActivityManagerService可以將Activity的狀態變化傳遞到用戶端的Activity對象。在ActivityThread.java的main入口方法中:public static void main(String[] args) { SamplingProfilerIntegration.start(); // CloseGuard defaults to true and can be quite spammy. We // disable it here, but selectively enable it later (via // StrictMode) on debug builds, but using DropBox, not logs. CloseGuard.setEnabled(false); Process.setArgV0("<pre-initialized>"); Looper.prepareMainLooper(); if (sMainThreadHandler == null) { sMainThreadHandler = new Handler(); } ActivityThread thread = new ActivityThread(); thread.attach(false); if (false) { Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG, "ActivityThread")); } Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited"); }調用了當前線程的Looper.loop()方法迴圈從messageQueue中取出訊息處理: /** * Run the message queue in this thread. Be sure to call * {@link #quit()} to end the loop. */ public static void loop() { Looper me = myLooper(); if (me == null) { throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread."); } MessageQueue queue = me.mQueue; // Make sure the identity of this thread is that of the local process, // and keep track of what that identity token actually is. Binder.clearCallingIdentity(); final long ident = Binder.clearCallingIdentity(); while (true) { Message msg = queue.next(); // might block if (msg != null) { if (msg.target == null) { // No target is a magic identifier for the quit message. return; } long wallStart = 0; long threadStart = 0; // This must be in a local variable, in case a UI event sets the logger Printer logging = me.mLogging; if (logging != null) { logging.println(">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.what); wallStart = SystemClock.currentTimeMicro(); threadStart = SystemClock.currentThreadTimeMicro(); } msg.target.dispatchMessage(msg); if (logging != null) { long wallTime = SystemClock.currentTimeMicro() - wallStart; long threadTime = SystemClock.currentThreadTimeMicro() - threadStart; logging.println("<<<<< Finished to " + msg.target + " " + msg.callback); if (logging instanceof Profiler) { ((Profiler) logging).profile(msg, wallStart, wallTime, threadStart, threadTime); } } // Make sure that during the course of dispatching the // identity of the thread wasn't corrupted. final long newIdent = Binder.clearCallingIdentity(); if (ident != newIdent) { Log.wtf(TAG, "Thread identity changed from 0x" + Long.toHexString(ident) + " to 0x" + Long.toHexString(newIdent) + " while dispatching to " + msg.target.getClass().getName() + " " + msg.callback + " what=" + msg.what); } msg.recycle(); } } }可以,看出,此loop方法是個死迴圈,通過queue.next()取出訊息後,然後通過handler的方法發送出去從前面看出,那個給message的target就是handler。前面傳入的然後通過msg.target.dispatchMessage(msg);方法分發訊息handler.java: /** * Handle system messages here. */ public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); } }callback預設為空白,因為不是自己new出的線程,沒有傳入這個參數。然後調用handleMessage方法處理。這個方法預設是空實現: /** * Subclasses must implement this to receive messages. */ public void handleMessage(Message msg) { }注釋已經說的很清楚,所以,你要處理訊息,必須重寫這個方法總的來說:對於主線程的話,就是首先放訊息到訊息佇列。然後主線程的looper迴圈檢查訊息佇列的訊息,因為looper對應線程。handler對應looper。然後looper把訊息給主線程的handler處理,實現獲得返回的狀態。如果不是主線程,系統沒有為新開的線程預設開啟looper和訊息機制。所以,必須你自己去處理在新線程中調用 Looper.prepare()方法構造looper對象 /** Initialize the current thread as a looper. * This gives you a chance to create handlers that then reference * this looper, before actually starting the loop. Be sure to call * {@link #loop()} after calling this method, and end it by calling * {@link #quit()}. */ public static void prepare() { if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); }//看到這句話了嗎?意思是為當前線程上綁定一個Looper對象。ThreadLocal是為了線程間共用變數用的//當下面調用Loooper.prepare後,就會為當前的線程建立一個唯一且只屬於當前線程的looper sThreadLocal.set(new Looper()); }然後主動啟動原來Activitythread.java--main()方法裡做的操作,調用loop()方法等待訊息:eg:class TestLooper extends Thread(){ public Handler mHandler; public void run(){ Looper.prepare() //下面執行個體化handler並處理訊息 ............ ............ Looper.loop() }} 下次,分析下handler內部封裝機制,其實,雖然我沒看,但是也能猜到,就是java中的那些線程啊,資料結構之類的結合,基礎,多麼的重要。累了,休息..........