Android之MessageQueue、Looper、Handler與消息循環

jopen 10年前發布 | 21K 次閱讀 Android Android開發 移動開發

在android的activity中有各種各樣的事件,而這些事件最終是轉換為消息來處理的。android中的消息系統涉及到:
 *  消息發送
 *  消息隊列
 *  消息循環
 *  消息分發
 *  消息讀取
  消息對應的重要類有MessageQueue、Looper、Handler,它們分別對應著消息隊列、消息循環和消息處理。

 

Handler類:
Handler主要用來發送消息和處理消息。每個handler實例都對應著一個線程和該線程的消息隊列。
當你創建一個handler對象時,該handler對象就屬于創建它的線程,并和該線程的消息隊列綁定,比如在主線程中創建handler對象,那么該 handler就只屬于主線程,并且和主線程的消息隊列綁定。(當然,每個線程都有自己的消息隊列,在android中,消息隊列是針對與線程的)。這樣,該handler就可以發送消息到該消息隊列并且處理該消息隊列的消息了。
當執行一些費時的操作時,比如需要遠程網絡訪問、下載等操作時,一般情況下都會啟動一個新的線程去操作。而不會放在ui線程去做,這樣可以防止 android的5秒無相應導致的ANR異常。子線程中返回的結果怎樣更新到ui線程呢,這時就可以通過handler來處理了。可以在主線程中定義 handler,然后通過主線程handler把子線程中的消息發送到主線程對應的消息隊列。在主線程中通過 handler.handlerMessage就可以處理消息了,并更新到ui了。
我們剛才說過,Handler主要是用來發送、處理消息的。那么消息循環、隊列是在哪里管理的。答案是:Looper、MessageQueue中。

Looper類:
looper類主要用來開啟線程的消息循環。默認情況下,系統在啟動的時候會為主線程創建消息循環。其他新創建的線程則沒有,
如果需要,可以在該線程內調用Looper.prepare()來啟用looper對象,然后調用Looper.loop()進入消息循環。
這樣該線程就具有消息循環機制了,比如:

    class LooperThread extends Thread {  
            public Handler mHandler;  

            public void run() {  
                Looper.prepare();  

                mHandler = new Handler() {  
                    public void handleMessage(Message msg) {  
                        // process incoming messages here  
                    }  
                };  

                Looper.loop();  
           }  
        }  

實際上消息隊列也是在Looper中創建的,看下Looper的loop()方法,這個方法就是用來做消息循環用的。

    public static final void loop() {  
             Looper me = myLooper(); //獲得當前線程的Looper對象  
             MessageQueue queue = me.mQueue;  //獲得當前線程的消息隊列  
            while (true) { //條件為true、一直循環執行。消息循環  
                Message msg = queue.next(); // might block  
                  //if (!me.mRun) {  
                //    break;  
                 //}  
                if (msg != null) {  
                    if (msg.target == null) {  
                         // No target is a magic identifier for the quit message.  
                        return;  
                   }  
                      if (me.mLogging!= null) me.mLogging.println(  
                            ">>>>> Dispatching to " + msg.target + " "  
                            + msg.callback + ": " + msg.whclearForRecycleat  
                             );  
                     msg.target.dispatchMessage(msg); //消息分發  
                    if (me.mLogging!= null) me.mLogging.println(  
                             "<<<<< Finished to    " + msg.target + " "  
                             + msg.callback);  
                     msg.recycle(); //消息已經分發出去,對消息進行回收處理  
                 }  
             }  
         }  

我們再來看Handler的構造函數,在Handler的構造函數中獲得當前線程的Looper對象、和消息隊列。消息隊列也是從looper中獲得的,剛才我們說過。

    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());  
                 }  
             }   
              //在Handler的構造函數中獲得當前線程的Looper對象、和消息隊列。消息隊列也是從looper中獲得的  
             mLooper = Looper.myLooper();  
             if (mLooper == null) {  
                 throw new RuntimeException(  
                     "Can't create handler inside thread that has not called Looper.prepare()");  
             }  
             mQueue = mLooper.mQueue;  
             mCallback = null;  
         }  

在handler中還有一些重要的方法:

 

handleMessage(Message)   //處理消息

dispatchMessage(Message)  //分發消息

sendMessage(Message)   //發送消息

 

到這里我們大致可以了解android中的消息流程大概是這樣的:
Handler獲得當前線程的Looper、MessageQueue,并且發送消息到MessageQueue中。 Looper對消息做循環,并通過 msg.target.dispatchMessage來分發消息(target應該就是handler)。然后 Handler.handlerMessage處理消息。

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!