1. 程式人生 > >Android6.0中的Handler訊息模型

Android6.0中的Handler訊息模型

在Android應用開發和系統功能開發中,經常用到多執行緒,而Handler訊息模型線上程間的訊息傳遞機制中佔有重要的地位。對於Handler的理解,最好的參考資料是Android Developer上面的Handler介紹。

通過一個Handler,可以允許我們傳送和處理一個Thread中的訊息佇列(MessageQueue)中的訊息(Message)。

Handler有兩種主要的用法:

  1. 將Message規劃到將來某個時間執行;
  2. 將某個動作放到另外一個執行緒中執行;

從上面的介紹裡面可以看出幾點了。

  1. 一個Handler對應一個執行緒,它操作的內容是一個Message,而這個message就是執行緒的處理單元。
  2. 如何向另外一個執行緒發起通訊,可以考慮通過該執行緒的Handler來實現。

我們從Handler的角度看,裡面包含兩個主體, Handler和Thread。下面我們就分析一下Android6.0裡面Handler和Thread的原始碼。

Handler原始碼分析

**原始碼地址:**frameworks/base/core/java/android/os/Handler.java

我們先從建構函式入手分析:


public Handler(Looper looper, Callback callback, boolean async) {
        mLooper = looper;
        mQueue = looper.mQueue;
        mCallback = callback;//handleMessage函式
mAsynchronous = async; }

裡面保留了mLooper和mQueue這兩個例項,而在其中顯然是Looper是主角。這個物件非常有意思,我們在繼續Handler原始碼分析之前,得先了解一下這個Looper。

Looper原始碼分析

Loop有圓環,成環,迴路的意思。

**原始碼地址:**frameworks/base/core/java/android/os/Looper.java

我們先打個岔,平常比較常用的方法如下:


//packages模組下面的NotificationPlayer類裡面的Thread子類

private
final class CreationAndCompletionThread extends Thread { @Override public void run() { Looper.prepare(); mLooper = Looper.myLooper(); synchronized(this) { //do things in the thread } Looper.loop(); } }

上面的Thread執行緒就有自己的Looper了,也就是說有自己的訊息迴圈模型,可以在其他的執行緒中向該執行緒傳送Message,並且在該執行緒中進行處理,從而達到執行緒間通訊。我們對run裡面的Looper呼叫進行分析:


private static void prepare(boolean quitAllowed) {
        sThreadLocal.set(new Looper(quitAllowed));
    }

這個sThreadLocal是一個執行緒本地儲存物件。為什麼要用這個呢?因為在一個程序中的多個執行緒實際是共享程序的開發資源的,而這個ThreadLocal實際上類似一個Map,儲存的是執行緒和執行緒獨享的變數的鍵值對。以執行緒本身為鍵,以執行緒獨享的變數(本例中為mLooper)為值。

public static void loop() {
    final Looper me = myLooper();
    final MessageQueue queue = me.mQueue;
    for (;;) {
        Message msg = queue.next();
        msg.target.dispatchMessage(msg);
    }
}

最後執行Looper.loop,啟動執行緒的訊息迴圈模型,不停從訊息佇列(MessageQueue)中獲取訊息,並且處理該訊息。

對比一下沒有Looper訊息迴圈機制的Thread:

new Thread(new Runnable() {
            @Override
            public void run() {/*body*/}
).start();

這個就是簡單的把這個執行緒新建出來,由系統排程,在某個時間執行裡面的run主題。注意:沒辦法向這個執行緒裡面傳送message讓它執行。

回到Handler

常用的Handler使用方式為:


private final Handler mResultHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case LOAD_RESULT:
                    resultLoad(msg);
                    break;
            }
        }
    };

直接在裡面定義的handleMessage裡面處理髮送過來的資訊。這個Message就是Looper.loop裡面的訊息迴圈機制裡面傳送過來的訊息。

總結

實現了訊息迴圈模型的執行緒裡面都含有一個對應的Looper物件,該物件裡面會維持一個訊息佇列,並且對佇列裡面的訊息逐個處理。處理訊息時,會將它傳送到該執行緒裡面新建的Handler物件的handleMessage進行處理。當然,也可以使用該Handler物件的post方法集,將訊息傳送到該Looper的訊息佇列裡面,以進入訊息迴圈模型。