Android之Looper

        Looper:循環器,是一個用於使線程運行一個消息(Message)循環的類。線程默認沒有關聯的消息循環,在建立它以前,在將要運行循環的線程中調用prepare方法,而後loop方法會處理消息直到循環結束。 java

        絕大多數消息循環是經過Handler類來Looper交互的。 ide

        下面是實現了Looper的線程的一個典型例子,使用分離的prepare方法和loop方法來建立一個用於跟Looper溝通的初始Handler。 oop

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

        先看準備工做的prepare方法: ui

public static final void prepare() {
    if (sThreadLocal.get() != null) {
        throw new RuntimeException("Only one Looper may be created per thread");
    }
    sThreadLocal.set(new Looper());
}

        每條線程只能綁定一個Looper,不然會拋出RuntimeException異常。若是不調用prepare方法,sThreadLocal.get()就會返回null。注意這是個靜態方法,在最後一行中綁定了一個作爲Looper的線程。怎麼綁定的呢,看看Looper的一個私有無參構造方法: spa

private Looper() {
    mQueue = new MessageQueue();
    mRun = true;
    mThread = Thread.currentThread();
}

        構造方法裏初始化了一個消息隊列、一個運行狀態的標誌以及綁定一個線程(建立者所在的線程)。prepare方法給了一個在真正的循環開始以前,參照Looper建立一個Handler的機會。注意:在run方法中初始化Handler以前,必須調用Looper.prepare(),否則會拋出一個運行時異常,由於Handler須要一個從Looper獲得的消息隊列(即構造方法裏面的mQueue)。調用prepare方法後必定要調用loop方法,而且調用quit方法退出循環。 線程

        接下來,看看在當前線程裏運行一個消息隊列的loop方法,用完後必定要調用quit方法結束循環: code

public static final void loop() {
    Looper me = myLooper();
    MessageQueue queue = me.mQueue;
    while (true) {
        Message msg = queue.next(); // might block
        if (msg != null) {
            if (msg.target == null) {
                // No target is a magic identifier for the quit message.
                return;
            }
            msg.target.dispatchMessage(msg);
            msg.recycle();
        }
    }
}

        高潮來了,上面說過,Looper的mQueue是Handler使用的消息隊列,loop方法啓動一個死循環從隊列中獲取數據,當隊列中沒有數據時,queue.next()會阻塞。當有數據時,msg.target(即Handler)就會調用dispatchMessage方法,進而調用Handler的handleCallback或者handlerMessage方法。從這些也能夠知道,若是Handler是在子線程的run方法中建立(以前必須調用Looper.prepare())的,那麼這個Handler的handleMessage或者handleCallback方法就是運行在子線程的。 隊列

相關文章
相關標籤/搜索