Android源碼閱讀之Looper

Looper在消息機制中的作用是從MessageQueue中取消息以及讓Handler去處理這個消息

在Looper類上面有一段說明,意思是消息機制在線程中的使用示例

* <pre>

*  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();

*      }

*  }</pre>

從上我們可以看到消息機制的創建

先是執行Looper.prepare---新建一個Looper並保存在ThreadLocal中

然後創建Handler---通過Looper.myLooper方法得到當前線程的Looper,並再一步得到messagequeue

最後執行Looper.loop方法開啓循環讀取消息,消息機制開始生效

Looper.prepare

我們可以看到在Looper類中定義了以下變量

static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();//作用保存Looper到當前線程

private static Looper sMainLooper// 主線程Looper

final MessageQueue mQueue;//消息隊列

接下來看下prepare方法

public static void prepare() {

    prepare(true);

}

private static void prepare(boolean quitAllowed) {

    if (sThreadLocal.get() != null) {

        throw new RuntimeException("Only one Looper may be created per thread");

    }

    sThreadLocal.set(new Looper(quitAllowed));

}

可以看到prepare最終調用的是prepare(boolean quitAllowed)方法

quitAllowed意思是 是否允許終止Messagequeue的循環

從prepare(boolean quitAllowed)我們可以看到一個線程最多隻能擁有一個Looper對象,

爲空則創建一個Looper對象並且保存到sThreadLocal中去

Looper構造函數

private Looper(boolean quitAllowed) {

    mQueue = new MessageQueue(quitAllowed);

    mThread = Thread.currentThread();

}

在構造函數中 創建了一個Messagequeue對象,並且得到了當前線程

這時候Looper與messagequeue已經完成了綁定

new MessageQueue(quitAllowed)中的quitAllowed表示當前的消息鏈表查詢能否允許被停止

prepare方法的作用是創建一個Looper保存在當前線程ThreadLocal中,並且完成Looper與MessageQueue的綁定

prepare在一般子線程開啓消息機制中才會被調用

在Android主線程開啓消息機制中調用的是prepareMainLooper()

public static void prepareMainLooper() {

    prepare(false);

    synchronized (Looper.class) {

        if (sMainLooper != null) {

            throw new IllegalStateException("The main Looper has already been prepared.");

        }

        sMainLooper = myLooper();

    }

}

可以看到主線程調用的prepare(boolean quitAllowed)中的quitAllowed值爲false這意味着主線程的Messagequeue不能被停止,也就是主線程的消息機制不會被停止

如何獲得當前線程保存的Looper對象

public static @Nullable Looper myLooper() {

    return sThreadLocal.get();

}

如何獲得主線程保存的Looper對象

public static Looper getMainLooper() {

    synchronized (Looper.class) {

        return sMainLooper;

    }

}

Looper.loop

執行了loop方法後,消息機制纔會開始工作

public static void loop() {

    final Looper me = myLooper();

    if (me == null) {

        throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");

    }

    ........

    for (;;) {

        Message msg = queue.next(); // might block

        if (msg == null) {

            // No message indicates that the message queue is quitting.

            return;

        }

........

            msg.target.dispatchMessage(msg);

        } finally {

            if (traceTag != 0) {

                Trace.traceEnd(traceTag);

            }

        }

.........

        msg.recycleUnchecked();

    }

}

從loop方法可以看出裏面是在不斷循環的從Messagequeue隊列中取出消息,只有當queue.next返回null時,循環停止,退出loop方法,消息機制失效

如果queue.next不返回null的話 則調用被取出的msg.target.dispatchMessage 回到msg.target指向的handler中處理

總結

Looper主要是完成了在當前線程中創建對象並且保存在ThreadLocal中,完成Looper與MessageQueue的綁定關聯,

開啓loop從MessageQueer取出消息處理

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章