解析Android消息處理機制java
——Handler/Thread/Looper & MessageQueueandroid
Keywords: Android Message HandlerThread Looper UML框架
本文解析Android如何利用Handler/Thread/Looper以及MessageQueue來實現消息機制的內部實現。知道了它的內部實現機理以後,之後再遇到使用它們時候的任何問題就得心應手、迎刃而解了。ide
Android利用執行在HandlerThread線程中的Looper的相應消息分發/處理,與其餘線程中的消息發送結合,實現完整的消息處理機制。本文首先介紹這些消息處理過程當中的參與者之間的關係,而後結合WifiService消息處理的實際實例,講解消息處理的全過程,最後還從線程視圖的角度,從新審視一下線程同步模型。函數
下圖是從Froyo從抽取出的HandlerThread、Looper和MessageQueue的關係圖。他們被定義在package android.os。oop
圖一:HandlerThread/Looper/MessageQueue實例關係this
HandlerThread是一個Thread,繼承自Thread。它保留着對Looper實例的引用,不過這裏還看不到HandlerThread、Looper和MessageQueue如何實例化,這要到2、HandlerThread/Looper/MessageQueue實例化以後才能看清如何實現的。spa
一看便知,Looper的構造函數是私有的,外界沒法直接實例化之;要實例化,只有經過Looper::prepare()。這樣HandlerThread就與Looper創建了對應關係。對如何創建的是否是已經火燒眉毛了,那就接着看下一小節。.net
上一節只是看了HandlerThread、Looper和MessageQueue之間的靜態視圖關係,他們具體如何實例化的,還要看動態的實例初始化過程。線程
圖二:HandlerThread/Looper實例化
總結一下,HandlerThread是被顯式地經過new建立的實例,而與它綁定在一塊兒的Looper是在HandlerThread的執行過程當中被實例化的,相應的MessageQueue也是在這個過程當中實例化的。
上節重點講了HandlerThread/Looper的實例化過程,它發生在Thread::run()這也是線程運行的關鍵,從圖二也看到了Looper::loop()這個消息處理的核心正是在這裏執行的,下面就看看它到底作了什麼。
圖三:Looper::loop()處理
圖中的全部序列是發生在一個無限循環體while (true) {} 中的。
在Looper::loop()消息處理的順序圖裏看到了Handler,這個消息分發處理的參與者。下面結合WifiHandler這個具體的Handler看它如何參與到消息的發送、分發和處理的。
WifiService中定義了以下的WifiHandler。
圖4、消息的發送、分發、處理者Handler
看Handler的構造函數是須要Looper的,從上面的分析知道,Looper是在HandlerThread執行中實例化的,Looper實例如何得到的呢?看圖一&圖二,知道HandlerThread保留着Looper的應用mLooper,並可經過getLooper()被外面獲取。而Handler的mQueue: MessageQueue能夠經過mLooper.mQueue得到。
因此,Wifi的HandlerThread,WifiHandler能夠這樣實例化:
圖5、消息發送
經過Message::obtain()能夠創建起Message和Target/Handler,what之間的關係,並獲得一個Message msg[序列1&2];而後經過msg.sendToTarget()就能夠用Handler來具體發送消息了[序列3&4];經過一系列的調用,最後會經過MessageQueue::enqueueMessage()把消息放到mMessages上[序列7],還會經過this.notify()通知正在等待新消息的線程,從新擁有MessageQueue的對象鎖,而處理該消息。
圖6、MessageQueue與Message的關係
至此,消息的發送,分發,處理基本上介紹完畢。
而要具體處理消息,從圖三的序列4就可知道,整個框架的最後消息的處理是經過Handler::handleMessager(msg: Message)來完成。因此若是有本身具體要處理的消息,只要override Handler的handleMessage(msg: Message)方法,並加入本身特定的對消息的處理便可。
要處理消息,就看看Message的屬性裏都有什麼。
圖7、Message屬性
重點關注public屬性what是區分具體什麼消息;能夠帶參數arg1, arg2。
上面介紹了消息處理的全過程,這些對於只是用來發送和處理消息的應用者來講,可能有些繁雜,這裏梳理一下從應用者角度看,怎麼使用之。
其實4、Handler實現具體消息處理中的WifiService就是一個典型的應用場景。
實現一個Handler的子類,並Override handleMessage()方法,亦即,實現消息處理函數handleMessage()。而後分別建立HandlerThread和Hanlder繼承類的實例。這樣就能夠如4.2裏那樣發消息了,而消息處理在handleMessage()中進行。
從應用者角度看,Looper和MessageQueue是消息處理的內部機制,能夠不關注它的實現細節(惟一要知道的,Handler實例化的時候,須要經過HandlerThread得到Looper的實例,從而能夠傳遞給Handler)。
下面再從線程的角度看一下,消息處理過程當中參與的線程,以及這些線程之間的同步。
顯然的,這裏有線程HandlerThread的參與,並且Looper::loop()就是執行在HandlerThread的run()方法裏,也就是在HandlerThread裏執行,這也就是說消息的分發處理和執行是在HandlerThread的線程上下文中。另外,還有至少一個線程存在,也就是建立了HandlerThread的線程B,以及執行消息發送的線程C,B和C有多是同一線程。
消息的發送是在另一個線程裏,就是由於有了多個線程的存在,纔有了線程的同步操做。可再次關注一下圖三和圖五中實現線程同步的Java原語wait()/notify()。
寫本文的初衷並非爲了寫它而寫它,是在研究Android中的Wifi實現時,遇到了實現Wifi的各類具體操做都是經過消息來實現的,就想探討一下ANDROID消息處理機制,這樣就邊看邊用ROSE畫了圖,等到消息的發送/接收/處理的過程都看完了,再回頭看一下整個UML圖,這不就整個一完整的消息處理機制嘛!
工做這麼多年過來了,回過頭來看看,本身積累了什麼呢,再看一下五、6年前鄙人的BLOG發現那時仍是留下了些東西的,並且寫本文時,重溫Java的線程同步機制時,看到當時寫的東西,發現若是是當時是本身理解的東西,而且用本身擅長的領域表達出來,本身回頭再看時,一目瞭然,幾個UML圖就能解決問題了。
修正記錄
消息發送分發處理的主要參與者是Looper, Handler,還有Thread的執行。不少應用場景有他們參與就可完成,HandlerThread卻是WifiService處理時消息處理的一個特例,因此,在這些關鍵點上去掉HandlerThread。