Handler、Looper、MessageQueue源碼解析

首先打開Looper類,可以看到頭部的說明中有一個小例子,如下:

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

這是一個在子線程中創(chuàng)建Handler的例子,我們就以這個例子來講解。

Looper.prepare();

在子線程中,在創(chuàng)建Handler之前先執(zhí)行了Looper.prepare(),我們先來看下Looper.prepare()的代碼:

static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();

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");
    }
    //創(chuàng)建Looper對象,并把Looper存入ThreadLocalMap
    sThreadLocal.set(new Looper(quitAllowed));
}

//ThreadLocal的set()方法
public void set(T value) {
    //獲取當(dāng)前線程
    Thread t = Thread.currentThread();
    //獲取當(dāng)前線程的ThreadLocalMap
    ThreadLocalMap map = getMap(t);
    //把ThreadLocal為key,Looper為value存入ThreadLocalMap
    if (map != null)
        map.set(this, value);
    else
        createMap(t, value);
}

//Looper的構(gòu)造方法,創(chuàng)建了一個MessageQueue
private Looper(boolean quitAllowed) {
    mQueue = new MessageQueue(quitAllowed);
    mThread = Thread.currentThread();
}

Looper.prepare()的作用就是創(chuàng)建一個Looper和一個MessageQueue對象,Looper.prepare()只能調(diào)用一次,再次調(diào)用就會拋throw new RuntimeException("Only one Looper may be created per thread")異常,所以每一個線程對應(yīng)唯一的一個Looper和一個MessageQueue。

new Handler()

public Handler() {
    this(null, false);
}

public Handler(Callback callback, boolean async) {
    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());
        }
    }

    //獲取當(dāng)前線程的Looper對象(Looper.myLooper()的源碼在下面)
    mLooper = Looper.myLooper();
    if (mLooper == null) {
        throw new RuntimeException(
            "Can't create handler inside thread that has not called Looper.prepare()");
    }
    //獲取當(dāng)前線程的Looper對應(yīng)的MessageQueue
    mQueue = mLooper.mQueue;
    mCallback = callback;
    mAsynchronous = async;
}

從上面可以看出Handler的構(gòu)造方法,其實就是獲取當(dāng)前線程的Looper和MessageQueue,我們通過Handler的sendMessage發(fā)送Message,都是把Message放到MessageQueue中。

public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
    MessageQueue queue = mQueue;
    if (queue == null) {
        RuntimeException e = new RuntimeException(
                this + " sendMessageAtTime() called with no mQueue");
        Log.w("Looper", e.getMessage(), e);
        return false;
    }
    return enqueueMessage(queue, msg, uptimeMillis);
}

private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
    //把當(dāng)前Handler對象賦值給msg.target
    msg.target = this;
    if (mAsynchronous) {
        msg.setAsynchronous(true);
    }
    //把Message放到MessageQueue中
    return queue.enqueueMessage(msg, uptimeMillis);
}

Looper.myLooper()

Looper.myLooper()先獲取當(dāng)前線程,再獲取當(dāng)前線程的ThreadLocalMap,然后從ThreadLocalMap中獲取先前存入的Looper。

public static @Nullable Looper myLooper() {
    return sThreadLocal.get();
}
//ThreadLocal的get()方法
public T get() {
    //獲取當(dāng)前線程
    Thread t = Thread.currentThread();
    //獲取當(dāng)前線程的ThreadLocalMap
    ThreadLocalMap map = getMap(t);
    if (map != null) {
        //以ThreadLocal為key從ThreadLocalMap取出保存的Looper
        ThreadLocalMap.Entry e = map.getEntry(this);
        if (e != null)
            return (T)e.value;
    }
    return setInitialValue();
}

Looper.loop()

循環(huán)從MessageQueue中取出Message,通過msg.target就是發(fā)送Message的Handler,調(diào)用Handler的dispatchMessage(msg)分發(fā)消息。

public static void loop() {
    //獲取當(dāng)前線程的Looper對象
    final Looper me = myLooper();
    if (me == null) {
        throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
    }
    final MessageQueue queue = me.mQueue;

    // Make sure the identity of this thread is that of the local process,
    // and keep track of what that identity token actually is.
    Binder.clearCallingIdentity();
    final long ident = Binder.clearCallingIdentity();

    //循環(huán)從MessageQueue中取出Message
    for (;;) {
        Message msg = queue.next(); // might block
        if (msg == null) {
            // No message indicates that the message queue is quitting.
            return;
        }

        // This must be in a local variable, in case a UI event sets the logger
        final Printer logging = me.mLogging;
        if (logging != null) {
            logging.println(">>>>> Dispatching to " + msg.target + " " +
                    msg.callback + ": " + msg.what);
        }

        final long traceTag = me.mTraceTag;
        if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {
            Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
        }
        try {
            //msg.target就是發(fā)送Message的Handler,dispatchMessage(msg)分發(fā)消息
            msg.target.dispatchMessage(msg);
        } finally {
            if (traceTag != 0) {
                Trace.traceEnd(traceTag);
            }
        }

        if (logging != null) {
            logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
        }

        // Make sure that during the course of dispatching the
        // identity of the thread wasn't corrupted.
        final long newIdent = Binder.clearCallingIdentity();
        if (ident != newIdent) {
            Log.wtf(TAG, "Thread identity changed from 0x"
                    + Long.toHexString(ident) + " to 0x"
                    + Long.toHexString(newIdent) + " while dispatching to "
                    + msg.target.getClass().getName() + " "
                    + msg.callback + " what=" + msg.what);
        }

        msg.recycleUnchecked();
    }
}

msg.target.dispatchMessage(msg)

Handler的dispatchMessage(msg)把Message交給對應(yīng)的方法處理,這里是handleMessage(msg)。

public void dispatchMessage(Message msg) {
    if (msg.callback != null) {
        handleCallback(msg);
    } else {
        if (mCallback != null) {
            if (mCallback.handleMessage(msg)) {
                return;
            }
        }
        handleMessage(msg);
    }
}

public void handleMessage(Message msg) {
}

總結(jié)

Looper的prepare()方法創(chuàng)建了一個Looper對象,并且保證每個線程最多只有一個Looper對象。在主線程中,系統(tǒng)已經(jīng)初始化了一個Looper對象,因此可以直接創(chuàng)建Handler,在子線程必須調(diào)用Looper.prepare()創(chuàng)建一個Looper對象,并調(diào)用Looper.loop()啟動它。

Handler的構(gòu)造方法,會獲取當(dāng)前線程的的Looper,進而獲得關(guān)聯(lián)的MessageQueue,Handler的sendMessage會給msg.target賦值為自身,然后把Message存入MessageQueue。

Looper不斷的從MessageQueue中取出Message,通過msg.target獲取對應(yīng)的Handler,調(diào)用Handler的dispatchMessage(msg)把Message交給對應(yīng)的方法處理。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容