Handler機(jī)制源碼分析

Handler是Android里面線程間通信的手段,它可以向自身持有的looper所在的線程發(fā)送消息進(jìn)行通信。
先看看典型的帶looper的線程的創(chuàng)建方法。

  *  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的注釋

Class used to run a message loop for a thread. Threads by default do not have a message loop associated with them; to create one, call {@link #prepare} in the thread that is to run the loop, and then {@link #loop} to have it process messages until the loop is stopped.

上面注釋的大意是,Looper類用來(lái)給一個(gè)線程運(yùn)行消息循環(huán)。線程默認(rèn)情況下是沒有消息循環(huán)的。使用Looper.prepare方法和Looper.loop來(lái)運(yùn)行循環(huán)并且讓它處理消息。

可以看到上面的代碼和注釋的說(shuō)明是一致的,在thread的run方法中,先調(diào)用Looper.prepare方法來(lái)初始化looper,然后調(diào)用Looper.loop來(lái)運(yùn)行循環(huán),并且初始化了handler

看看Looper的初始化過(guò)程Looper.prepare

    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));
    }
    ...
    public static @Nullable Looper myLooper() {
        return sThreadLocal.get();
    }

prepare方法new出了一個(gè)looper對(duì)象并把它放入了一個(gè)ThreadLocal變量,這樣每一個(gè)帶looper的線程將維護(hù)自己的一個(gè)looper對(duì)象。

    private Looper(boolean quitAllowed) {
        mQueue = new MessageQueue(quitAllowed);
        mThread = Thread.currentThread();
    }

looper構(gòu)建的時(shí)候初始化了mQueue變量,它是一個(gè)MessageQueue對(duì)象。

再來(lái)看看Looper.loop()方法是如何運(yùn)行循環(huán)的

public static void loop() {
  ...
  for (;;) {
            Message msg = queue.next(); // might block
            ...
            ...
            msg.target.dispatchMessage(msg);
            ...
  }
}

loop()方法中,通過(guò)一個(gè)死循環(huán)不斷地通過(guò)調(diào)用MessageQueue的next方法獲取message,在注釋中可以看到,next方法可以被阻塞,如果沒有獲取到message就一直阻塞在這里直到獲取到為止。然后調(diào)用msg.target的dispatchMessage方法,這里的msg.target其實(shí)就是handler,dispatchMessage方法就是我們創(chuàng)建handler的時(shí)候重寫的dispatchMessage方法。

MessageQueue是一個(gè)典型的生產(chǎn)者/消費(fèi)者隊(duì)列,線程通過(guò)looper的loop方法不斷地消費(fèi)MessageQueue中的message,而生產(chǎn)者則是handler。
下面我們看看生產(chǎn)者h(yuǎn)andler是如何向MessageQueue發(fā)送message的。

先看看handler的創(chuàng)建過(guò)程,我們都知道不帶參數(shù)的handler創(chuàng)建的時(shí)候必須在looper線程內(nèi)創(chuàng)建,然后才能在其它線程中使用該handler向該線程發(fā)送消息,為啥要在線程內(nèi)創(chuàng)建呢?

    public Handler(Callback callback, boolean async) {
        ...
        mLooper = Looper.myLooper();
        if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread " + Thread.currentThread()
                        + " that has not called Looper.prepare()");
        }
        mQueue = mLooper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }

不帶參數(shù)的handler構(gòu)造器最終調(diào)用了上面這個(gè)構(gòu)造器??梢钥吹嚼锩嬲{(diào)用了
mLooper = Looper.myLooper();
這里的myLooper方法獲取的就是前面說(shuō)的存儲(chǔ)在TheadLocal變量里面的當(dāng)前線程的looper,然后又調(diào)用了
mQueue = mLooper.mQueue;
這里的mQueue就是上面說(shuō)的MessageQueue。
所以就很明顯啦,handler在哪個(gè)線程進(jìn)行初始化,就會(huì)持有哪個(gè)線程的looper以及該線程looper內(nèi)的MessageQueue,進(jìn)而就會(huì)把消息發(fā)送到該線程的looper內(nèi)的messageQueue。

事實(shí)上,Handler類是提供了帶Looper參數(shù)的構(gòu)造器的,使用這種構(gòu)造器就不需要在Thread的run方法內(nèi)部來(lái)初始化Handler了。

再來(lái)看handler發(fā)送message的過(guò)程,Handler的眾多sendMessage和post方法最終都會(huì)調(diào)用這個(gè)方法

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

繼續(xù)跟進(jìn)

    private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
        msg.target = this;
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
    }

可以看到把msg.target設(shè)置為了this,這里的this就是handler對(duì)象自己。
然后調(diào)用了MessageQueue的enqueueMessage方法,跟進(jìn)去看看。

    boolean enqueueMessage(Message msg, long when) {
        ...
        synchronized (this) {
            ...
            Message p = mMessages;
            boolean needWake;
            if (p == null || when == 0 || when < p.when) {
                // New head, wake up the event queue if blocked.
                msg.next = p;
                mMessages = msg;
                needWake = mBlocked;
            } else {
                // Inserted within the middle of the queue.  Usually we don't have to wake
                // up the event queue unless there is a barrier at the head of the queue
                // and the message is the earliest asynchronous message in the queue.
                needWake = mBlocked && p.target == null && msg.isAsynchronous();
                Message prev;
                for (;;) {
                    prev = p;
                    p = p.next;
                    if (p == null || when < p.when) {
                        break;
                    }
                    if (needWake && p.isAsynchronous()) {
                        needWake = false;
                    }
                }
                msg.next = p; // invariant: p == prev.next
                prev.next = msg;
            }

            // We can assume mPtr != 0 because mQuitting is false.
            if (needWake) {
                nativeWake(mPtr);
            }
        }
        return true;
    }

MessageQueue里面維護(hù)了一個(gè)mMessages域,它是一個(gè)Message,可以看到Message是一個(gè)鏈表結(jié)構(gòu),enqueueMessage做的主要事情之一就是把message插入到mMessages中的合適位置。
這樣,通過(guò)enqueueMessage方法,message就被handler放到MessageQueue中了。

綜上,Handler的機(jī)制可以總結(jié)如下:

  1. Thread的run方法中,創(chuàng)建了一個(gè)ThreadLocal類型的域Looper。
  2. Looper又創(chuàng)建并持有一個(gè)MessageQueue。
  3. 然后Handler被創(chuàng)建并持有Looper和MessageQueue的引用。
  4. MessageQueue是一個(gè)生產(chǎn)者/消費(fèi)者隊(duì)列,Looper通過(guò)loop()方法中的死循環(huán)不斷地向隊(duì)列獲取Message,獲取到則調(diào)用Message所持有的Handler對(duì)象的dispatchMessage方法;如果獲取不到則阻塞在那里。
  5. 被創(chuàng)建出來(lái)的Handler對(duì)象可以被其它的線程所持有并且生產(chǎn)出Message發(fā)送到隊(duì)列中。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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