Android 之 Looper、MessageQueue、Handler 與訊息迴圈

yangxi_001發表於2013-11-15

在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處理訊息

相關文章