解析Android消息處理機制:Handler/Thread/Looper & MessageQueue

解析Android消息處理機制java

——Handler/Thread/Looper & MessageQueueandroid

Keywords: Android Message HandlerThread Looper UML框架

           本文解析Android如何利用Handler/Thread/Looper以及MessageQueue來實現消息機制的內部實現。知道了它的內部實現機理以後,之後再遇到使用它們時候的任何問題就得心應手、迎刃而解了。ide

           Android利用執行在HandlerThread線程中的Looper的相應消息分發/處理,與其餘線程中的消息發送結合,實現完整的消息處理機制。本文首先介紹這些消息處理過程當中的參與者之間的關係,而後結合WifiService消息處理的實際實例,講解消息處理的全過程,最後還從線程視圖的角度,從新審視一下線程同步模型。函數

 

1、HandlerThread/Looper/MessageQueue的前世此生

下圖是從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

 

2、HandlerThread/Looper/MessageQueue實例化

        上一節只是看了HandlerThread、Looper和MessageQueue之間的靜態視圖關係,他們具體如何實例化的,還要看動態的實例初始化過程。線程

圖二:HandlerThread/Looper實例化

 

 

  • HandlerThread是一個Thread,在它被實例化並執行start()[序列1&2]以後,它的run()方法會在它本身的線程空間執行[序列3]。
  • 上節已經提到了Looper的實例化是經過Looper::prepare實現的,圖中能夠看到Looper::prepare()正是在HandlerThread::run()中被調用而實例化[序列4&5]的。
  • MessageQueue是在Looper的私有構造函數Looper()中實例化的。

 

總結一下,HandlerThread是被顯式地經過new建立的實例,而與它綁定在一塊兒的Looper是在HandlerThread的執行過程當中被實例化的,相應的MessageQueue也是在這個過程當中實例化的。

3、Looper::loop分發處理消息

      上節重點講了HandlerThread/Looper的實例化過程,它發生在Thread::run()這也是線程運行的關鍵,從圖二也看到了Looper::loop()這個消息處理的核心正是在這裏執行的,下面就看看它到底作了什麼。

圖三:Looper::loop()處理

 

圖中的全部序列是發生在一個無限循環體while (true) {} 中的。

  • mQueue:MessageQueue是Looper保留的一份引用,經過它的next()[序列1]獲取MessageQueue中的下一個要處理的消息,這個過程當中若是沒有相應的消息,執行它的線程會用this.wait()釋放它所擁有的MessageQueue的對象鎖而等待。
  • 一旦有消息到來[序列2],Looper會用得到的Message的Handler(msg.target)來分發處理消息[序列3&4]。消息處理完以後,還要回收[序列5]。

4、Handler實現具體消息處理

        在Looper::loop()消息處理的順序圖裏看到了Handler,這個消息分發處理的參與者。下面結合WifiHandler這個具體的Handler看它如何參與到消息的發送、分發和處理的。

 

4.1 Handler實例化

        WifiService中定義了以下的WifiHandler。

圖4、消息的發送、分發、處理者Handler

 

      看Handler的構造函數是須要Looper的,從上面的分析知道,Looper是在HandlerThread執行中實例化的,Looper實例如何得到的呢?看圖一&圖二,知道HandlerThread保留着Looper的應用mLooper,並可經過getLooper()被外面獲取。而Handler的mQueue: MessageQueue能夠經過mLooper.mQueue得到。

 

因此,Wifi的HandlerThread,WifiHandler能夠這樣實例化: 

[java]  view plain copy
 
  1. HandlerThread wifiThread = new HandlerThread("WifiService");  
  2. wifiThread.start();  
  3. mWifiHandler = new WifiHandler(wifiThread.getLooper());  

 

4.2 消息發送

圖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.3 消息處理

        而要具體處理消息,從圖三的序列4就可知道,整個框架的最後消息的處理是經過Handler::handleMessager(msg: Message)來完成。因此若是有本身具體要處理的消息,只要override Handler的handleMessage(msg: Message)方法,並加入本身特定的對消息的處理便可。

 

        要處理消息,就看看Message的屬性裏都有什麼。

圖7、Message屬性

 

重點關注public屬性what是區分具體什麼消息;能夠帶參數arg1, arg2。

 

5、從新審視

5.1 應用指南

        上面介紹了消息處理的全過程,這些對於只是用來發送和處理消息的應用者來講,可能有些繁雜,這裏梳理一下從應用者角度看,怎麼使用之。

        其實4、Handler實現具體消息處理中的WifiService就是一個典型的應用場景。

        實現一個Handler的子類,並Override handleMessage()方法,亦即,實現消息處理函數handleMessage()。而後分別建立HandlerThread和Hanlder繼承類的實例。這樣就能夠如4.2裏那樣發消息了,而消息處理在handleMessage()中進行。

        從應用者角度看,Looper和MessageQueue是消息處理的內部機制,能夠不關注它的實現細節(惟一要知道的,Handler實例化的時候,須要經過HandlerThread得到Looper的實例,從而能夠傳遞給Handler)。

 

5.2 線程角度

        下面再從線程的角度看一下,消息處理過程當中參與的線程,以及這些線程之間的同步。

        顯然的,這裏有線程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。

相關文章
相關標籤/搜索