Handler消息機制源碼全量解析

Android版本: 基於API源碼26,Android版本8.0。

本片文章的目的在於全面的瞭解Handler。它是如何傳遞消息的?是如何阻塞和喚醒線程的(僅限於Java層面)?MessageQueue到底是怎麼存儲和取出Message?延遲消息是怎麼被髮送的?

一 、Handler定義:

Handler是一套消息傳遞的機制。設計用來讓工作線程跟主線程之間進行消息傳遞。同時也解決了多線程同時更新UI的問題。Android系統設定子線程是不能更新UI的,當子線程一定要做更新UI的操作時,可以使用Handler將消息從子線程帶到主線程,並能保證消息的同步性。

二 、基本用法:

  • 在主線程中使用:
//實例化Handler對象。
Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
        }
};
//創建併發送消息
Message obtain = Message.obtain();
obtain.what = 100;
handler.sendMessage(obtain);

  • 在子線程中使用,一旦使用該子線程是不會自動結束的,除非手動結束:
//爲子線程中創建Looper對象。
Looper.prepare();
//實例化Handler對象。
Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
        }
};
//創建併發送消息。
Message obtain = Message.obtain();
obtain.what = 100;
handler.sendMessage(obtain);
//開啓消息循環。
Looper.loop();

如果先調用Looper.prepare()、Looper.loop()再handler.sendMessage(obtain),那麼消息會成功的發送成功嗎?

三 、源碼解析:

Handle的消息傳遞過程中涉及到了幾個重要的類:Handler、Message、Looper、MessageQueue。

  • Handler

官方的解釋:Handler允許您發送和處理MessageMessageQueue有關聯的可運行對象Runnable。每個Handler實例都與一個線程和該線程的消息隊列關聯,在創建的時候就會直接關聯起來。Handler將Message和Runnable傳遞到消息隊列中,並在它們從消息隊列中出來時執行它們。

Handler被用在兩個主要的地方:讓Message和Runnable定時執行;在非UI線程中將Message或者Runnable發送到主線程。

當應用程序創建進程時,其主線程專用於運行消息隊列,該隊列負責管理頂級應用程序對象(activities、broadcast receivers等)及其創建的任何窗口。

也就是Handler是用來專門發送和處理消息的。發送是隻發送到對應的消息隊列就好了。

  • Message:

官方解釋:定義包含描述和可發送到{@link handler}的任意數據對象的消息。此對象包含兩個額外的int字段和一個extra對象字段,在許多情況下允許您不進行分配。

也就是Message是Handler傳遞的元數據,其內部可以包含很多信息:what、arg1、arg2,、obj等。Handler發送的也是Message對象,處理的也是Message對象。所以Message肯定是序列化的,繼承自Parcelable。內部維護了一個緩存池,避免創建多餘的消息對象,緩存池的設計是Android系統源碼一貫的作風,在ViewRootImpl處理點擊消息的時候,也有類似設計。該緩存池的大小爲50,超過該緩存就會直接創建Messsage對象。

  • Looper:

官方解釋:Looper類用於爲線程運行消息循環。默認情況下,線程沒有與之關聯的消息循環;若要創建一個消息循環,請在要運行該循環的線程中調用 prepare()方法,然後調用loop()使其處理消息,直到循環停止。

也就是Handler只是將Message數據放到了MessageQunue中,Looper纔是從MessageQunue中取出消息,並將消息發送到正確的Handle中去。一個線程中存在一個Looper,Looper中維護着MessageQueue。Looper.prepare()方法是創建Looper跟MessageQueue,再發送消息之後調用Looper.loop()方法,開啓消息循環,也就是不停的從消息隊列中那出消息處理。

  • MessageQueue:

該機制中核心的存在。主要是用來操作Message的,實際上內部並沒有一個集合或者隊列去存儲Message,而是由Message組成的單鏈表結構。在Message的內部有個next屬性,屬性聲明爲Message對象,也就是Message自身就可組成一個隊列。MessageQunue的目的就是增刪對比Message。比如:第一個Message對象來了(m1),那麼它的next屬性是空的,然後又來了一個Message(m2)。發現m1還沒執行完畢,那麼就將m2的對象賦值給m1的next屬性,當m1執行完畢之後,取出自己的next屬性,如果不爲null,那就接着執行next屬性表示的Message,也就是m2。

當了解完每個類的職責之後,發送的消息的流程就會清晰的很多。

一般的,一個Thread應該只有一個Looper和MessageQueue。可以有多個Handler對象。當你在主線程中創建Handler的時候,你是不需要調用Looper.prepare()的,因爲主線程已經創建過了。創建Looper的線程決定了消息最終是在那個線程中被處理的。你在子線程中使用Handler對象發送消息,如果你的Looper是主線程中創建的,那麼處理消息的還是在主線程中,你發送消息的線程環境是無關緊要的。

Handler創建源碼解析:

Handler類是個普通的Java類,可以被繼承。創建方式爲:

//一般通過new的方法去創建。
Handler handler = new Handler();

Handler有七個構造方法,三個是被隱藏掉的。被註解@hide註釋之後,通過api是訪問不到的:

  //Handler.java  
    public Handler() {
        this(null, false);
    }
    public Handler(Callback callback) {
        this(callback, false);
    }

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

    public Handler(Looper looper, Callback callback) {
        this(looper, callback, false);
    }
   /**
     * @hide
     */
    public Handler(boolean async) {
        this(null, async);
    }

   /**
     * @hide
     */
    public Handler(Callback callback, boolean async) {
        //。。。省略代碼
        //獲取Looper對象。
        mLooper = Looper.myLooper();
        //。。。省略代碼
        //獲取MessageQueue。
        mQueue = mLooper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }

    /**
     * @hide
     */
    public Handler(Looper looper, Callback callback, boolean async) {
        mLooper = looper;
        mQueue = looper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }

可以看到構造參數中可以傳入的類型:Callback接口,Looper對象,布爾值async。首先Callback接口也是處理消息的:

//Handler.java 
public interface Callback {
        /**
         * @param msg A {@link android.os.Message Message} object
         * @return True if no further handling is desired
         */
        public boolean handleMessage(Message msg);
}

Handler類內部也有handleMessage()方法,使用的時候完全可以重寫該方法。Handler又提供該接口的目的也就是你可以不用實現Handler類中的方法也能處理消息,這樣自由一點。

如果構造方法中你傳入了Looper對象,就不需要去創建Looper對象了。至於布爾值async則是決定當前發送的Message是否是異步的消息,異步消息可以不受同步屏障的影響。在ViewRootImpl接收到繪製信號的時候,就會在UI Handler中發送一個同步屏障,這將阻止當前Handler處理所有的同步消息,然後讓該此異步消息先執行。Handler的創建過程很簡單,接下來看Message的創建過程。

Message創建源碼解析:

Message類是final的不能被繼承。實現了Parcelable接口。Message並沒有特殊的構造方法,所以直接就可new出來:

Message message = new Message();

另外系統推薦的獲取Message的方法爲:

Message obtain = Message.obtain();

obtain()方法有很多的重載方法,根據參數的不同構造不同的Message對象。該過程都是在Message內部實現的,對於調用着來說是透明的,下面來分析下基礎的obtain()方法:

//Message.java。
public static Message obtain() {
        synchronized (sPoolSync) {
            //判斷緩存池是否爲null。
            if (sPool != null) {
                Message m = sPool;
                //取出一個Message。
                sPool = m.next;
                m.next = null;
                //默認的flag爲0。
                m.flags = 0; // clear in-use flag
                //大小減一。
                sPoolSize--;
                return m;
            }
        }
        //否則就new一個
        return new Message();
    }

sPool是一個Message對象,相當於緩存隊列的頭指針。Mesage有個next屬性,該屬性還是Message對象。當調用該方法的時候,就從sPool中取出下一個Message也就是m.next,然後將m.next賦值給sPool,也就是重置隊列頭,然後返回之前的隊列頭m。這種是典型的單向鏈表結構,Android系統的源碼中很多地方都用到。然後在Message的reaycle()方法中,將使用過的Message存放到sPool代表的隊列中。

//Message.java。
public void recycle() {
        if (isInUse()) {
            return;
        }
        recycleUnchecked();
    }

    void recycleUnchecked() {
    //。。。省略代碼
        synchronized (sPoolSync) {
            //判斷緩存的數量是否小於規定值的
            if (sPoolSize < MAX_POOL_SIZE) {
                //將隊列頭指針指向下一個元素
                next = sPool;
                //隊列頭重置,這樣新的消息就變成了隊列的第一個元素,之前sPool表示的消息就變成該消息的next。
                sPool = this;
                sPoolSize++;
            }
        }
    }

Message的創建很簡單,需要注意的就是這個緩存池的原理。

消息發送流程源碼解析:

Handler handler = new Handler(new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {
            return false;
        }
    });

 Message obtain = Message.obtain();
 obtain.what = 100;
 handler.sendMessage(obtain);

上述代碼即可發送一個消息數據。不管是sendMessage()還是sendMessageDelayed()或者sendEmptyMessage()方法,最終都是調用的sendMessageAtTime()方法,sendEmpty***系列是Handler自己創建了一個空的Message,只是在使用着看起來是發送了一個空的消息一樣,這裏不再分析:

//Handler.java。
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);
    }

該方法中只是判斷了MessageQueue是否爲null。

//Handler.java。
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
       //該消息的目標Handler爲當前發送消息的Handler。
        msg.target = this;
        //如果是異步消息的話就設置爲異步標記。
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
    }

對Message對象做了一些標記之後就調用了MessageQueue的enqueueMessage()方法,這兩個標記都是很重要的,一個是設置目標Handler,這樣消息就不會讓錯誤的Handler處理。另外一個是表明消息是否是異步的,一般使用的時候都是同步消息,UI線程畢竟是線程不安全的:

//Message.java。 
public void setAsynchronous(boolean async) {
        if (async) {
            flags |= FLAG_ASYNCHRONOUS;
        } else {
            flags &= ~FLAG_ASYNCHRONOUS;
        }
    }

接着看queue.enqueueMessage()方法:

//MessageQueue.java。
boolean enqueueMessage(Message msg, long when) {
       //如果消息沒有目標Handler就拋出異常。
        if (msg.target == null) {
            throw new IllegalArgumentException("Message must have a target.");
        }
        //消息正在處理中 也拋出異常。
        if (msg.isInUse()) {
            throw new IllegalStateException(msg + " This message is already in use.");
        }
       //做了同步處理
        synchronized (this) {
            //當前的消息隊列已經結束了。mQuitting = true。
            if (mQuitting) {
                IllegalStateException e = new IllegalStateException(
                        msg.target + " sending message to a Handler on a dead thread");
                Log.w(TAG, e.getMessage(), e);
                msg.recycle();
                return false;
            }
            //標記正在處理中
            msg.markInUse();
            //消息的倒計時,多久之後發出。
            msg.when = when;
            //mMessages表示當前準備處理消息。
            Message p = mMessages;
            boolean needWake;
            //1.當前要處理的消息爲null。2.需要馬上發送,延遲時間爲0。3.如果當前要處理的消息的延遲比正在處理的消息時間段。
            //上面三個條件滿足一個就執行。如果是第一條消息if肯定會執行,如果來了第二條Message,但是第一條Message還沒執行完,也就是mMessages不爲null,消息的when還等於0,那麼也要直接執行,也就是添加到隊列的頭部。所以markInUse()方法還是很有必要的。
            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 {
                //當下一條消息來的時候發現前面還有消息沒執行完,並且當前的消息也不是立馬就執行的,或者等待的時間比正在執行的消息要長,那麼就執行到這邊。
               
                //p.target == null表示當前的消息是一個同步屏障。
                //needWake = true,說明當前的前一條消息是個同步屏障,並且當前的這條消息是個異步消息。
                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;
            }
            //插入隊列中間。通常我們不必喚醒事件隊列,除非隊列的開頭有一個屏障,並且消息是隊列中最早的異步消息。       
            //判斷是否喚醒線程。
            if (needWake) {
                nativeWake(mPtr);
            }
        }
        return true;
    }

上面的入對列操作很複雜:

  1. 一條新的消息到了,調用消息的markInUse方法。
  2. 判斷是否要立馬執行該消息。條件有三個:當前要處理的消息爲null;延遲時間爲0;如果當前要處理的消息的延遲時間比正在處理的消息時間短。
  3. 滿足步驟2的三個條件,就將當前的消息放到消息對列的頭部位置。needWake變量賦值。
  4. 當一條新的消息到來的時候,不滿足步驟2,也就是當前有正在執行的消息,並且該消息需要延遲發送,延遲的時間還比較長。那麼就會執行else方法。
  5. 走到else方法中,要先判斷當前正在執行的Message是否是一個同步屏障,也就是 p.target == null,然後判斷當前的消息是否是一個異步消息,因爲異步消息的話,是需要立馬執行的。然後有個For循環,判斷當前的隊列中是否有個異步消息還在處理中,有的話也就是 if (needWake && p.isAsynchronous())會執行,那麼此條消息就不能立馬執行。否則就要加入到隊列中等待了。
  6. 判斷needWake,是否喚醒線程。

經過上面的步驟,Handler將發送的Message放入到了消息隊列中。Handler類的職責已經結束了。下面來看Looper到消息隊列中取數據。

Looper源碼解析:

Looper類的註釋中說明了,在使用的時候要先調用Looper.prepare()方法,最後調用Looper.loop()方法。下面先看下prepare()方法:

   //Looper.java。
   //該方法是可以在任何線程中調用。
   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));
    }
    //該方法在ActivityThread創建的時候會被調用。
    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()系列方法就是創建一個Looper對象。採用prepareMainLooper()方法創建的Looper不會終止消息循環,其他的都可以被終止掉,也就是quitAllowed = true/fasle的問題。Looper創建結束之後看下loop()方法:

//Looper.java。
public static void loop() {
        final Looper me = myLooper();
         //。。。省略日誌代碼
        //Handler跟Looper用的是同一個隊列。
        final MessageQueue queue = me.mQueue;
        //確保此線程的標識是本地進程的標識,並跟蹤該標識令牌的實際內容。
        Binder.clearCallingIdentity();
        final long ident = Binder.clearCallingIdentity();

        for (;;) {
            //從消息隊列中取出下一條消息。
            Message msg = queue.next(); // might block
            if (msg == null) {
                // No message indicates that the message queue is quitting.
                return;
            }
            //。。。省略日誌代碼
            try {
                //msg.target就是Handler,然後分發消息。
                msg.target.dispatchMessage(msg);
                end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
            } finally {
              //。。。省略日誌代碼
            }
           //。。。省略日誌代碼
            //消息處理結束之後回收消息。
            msg.recycleUnchecked();
        }
    }

loop()方法要做的就是不停的從MessageQueue中獲取消息,所以就使用了For死循環。拿到消息之後,開始分發消息,最後將消息回收。重點在於Message的next()和Handler的dispatchMessage()以及最後Message的recycleUnchecked()方法了。先看next()方法:

//MessageQueue.java
Message next() {
        //如果消息循環已經退出並被釋放,則返回此處。如果應用程序在退出後嘗試重新啓動不受支持的循環程序,則可能發生這種情況。
        final long ptr = mPtr;
        if (ptr == 0) {
            return null;
        }
        //空閒時待處理的IdleHandler的數量。默認爲-1。
        int pendingIdleHandlerCount = -1; // -1 only during first iteration
        //下次輪詢超時毫秒
        int nextPollTimeoutMillis = 0;
        //開啓死循環。要麼阻塞,要麼獲取到Message。
        for (;;) {
            //將當前線程中掛起的任何綁定器命令刷新到內核驅動程序。在執行可能會阻塞很長時間的操作之前調用,以確保已釋放任何掛起的對象引用,以防止進程佔用對象的時間超過所需時間,這將非常有用。
            if (nextPollTimeoutMillis != 0) {
                Binder.flushPendingCommands();
            }
            //該方法可能會被阻塞,nextPollTimeoutMillis = -1的時候,將無限期的阻塞。也就是說當該方法有返回值的時候,那就代表該過程不會被阻塞,也就是會執行下面的代碼邏輯,也就是將會至少取出一個消息。
            nativePollOnce(ptr, nextPollTimeoutMillis);

            synchronized (this) {
                // 獲取系統時間。
                final long now = SystemClock.uptimeMillis();
                //該Message是表示將被執行的消息的前一個消息,有可能是從消息隊列的中間取出一個消息執行,這樣需要將被取出消息的next拼接到被取出消息的上一個消息的next上,這樣隊列不會被斷開。
                Message prevMsg = null;
                //隊列的頭消息。每次取出一個消息的時候都會將mMessages指向新的消息。
                Message msg = mMessages;
                if (msg != null && msg.target == null) {
                   //執行到這裏說明當前的消息是一個同步屏障,也就是將阻止所有的同步消息。
                   //找出隊列中的第一個異步消息,沒有異步消息msg就是null。 
                    do {
                        //找出消息的上一個消息。
                        prevMsg = msg;
                        //當前找出的消息。
                        msg = msg.next;
                    } while (msg != null && !msg.isAsynchronous());
                }
                //這裏並不是else語句,所以就是不是同步屏障就直接執行到這裏。
                if (msg != null) {
                    if (now < msg.when) {
                        // 下一條消息尚未準備好。設置一個超時,以便在它準備好時喚醒。也就是nextPollTimeoutMillis參數其實就是上面nativePollOnce()本地方法的參數,也就是阻塞的時長。
                        nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
                    } else {
                        //走到這裏說明找到了符合要求的Message,準備返回了。
                        mBlocked = false;
                        if (prevMsg != null) {
                            //prevMsg不爲null表示當前的msg是一個異步消息,那麼其值表示msg消息的上一個消息。也就是msg是從隊列中間取出來的,那麼就需要把隊列拼接完整了。
                            prevMsg.next = msg.next;
                        } else {
                            //走到這裏說明msg是一個同步消息,也是從隊列的頭部獲取到的,那麼就重置mMessages爲msg的下一個消息。
                            mMessages = msg.next;
                        }
                         //清空該消息的next屬性,這樣該消息就是一個獨立的消息。在上一步中該消息的next屬性已經賦給了隊列中的其它Message。
                        msg.next = null;
                        //標記正在使用
                        msg.markInUse();
                        return msg;
                    }
                } else {
                    // 沒有消息就爲-1.-1就表示該線程將無限期的阻塞。
                    nextPollTimeoutMillis = -1;
                }
                //處理完所有掛起的消息後,立即處理退出消息。
                if (mQuitting) {
                    dispose();
                    return null;
                }
                //。。。省略了空閒時處理IdleHandler的邏輯。IdleHandler對象,IdleHandler是一個接口,也就是繼承了該接口的事物將會在MessageQueue空閒的時候去處理。GC機制就是採用的這個東西觸發的。
               if (pendingIdleHandlerCount <= 0) {
                    //沒有東西可以執行了,就開始等待工作。
                    mBlocked = true;
                   //continue繼續執行for循環,然後在執行nativePollOnce()方法,線程阻塞。
                    continue;
                }
        }
    }

在Looper的loop()方法中第一個重要的就是MessageQueue的next()方法。該方法有以下幾點:

  1. 先開啓一個For死循環,做的跟Looper的loop()方法一樣。之後先阻塞線程,通過調用nativePollOnce()方法。當線程被喚起,也就是nativePollOnce()方法有返回值了,就執行後面的邏輯。
  2. 先獲取當前的時間,然後跟消息的延遲時間做對比。mMessages變量表示的就是消息隊列中的頭佈局,在MessageQueue的equeueMessage()方法中先被賦值,先是說第一此賦值的,接着在next()方法中還會被賦值。
  3. 判斷Message是不是一個同步屏障,稍後解釋。也就是msg.target == null,是的話就要拿出隊列中第一個異步消息,也就是Message的isAsynchronous()方法返回true。如果不是同步屏障,就繼續往下走。
  4. 這裏再次都Message判空,是因爲上一步,如果當前的消息是同步屏障的話,又找不到異步消息,那就可能返回null。
  5. 消息不爲null的時候,就判斷消息的延遲時間是否已經到了。如果還沒到的話,就計算出剩餘的事件,然後傳值給nextPollTimeoutMillis變量,第1步的時候nativePollOnce()方法會用到該值,判斷倒計時多久之後喚醒線程。所以該倒計時時間確定之後,MessageQueue的next()方法中的for循環再次執行到nativePollOnce()方法的時候,就會執行該倒計時。
  6. 如果需要立馬執行的話,mBlocked先變爲false,也就是在MessageQueue的queueMessage()方法此時添加Message的時候就不用喚醒線程了。之後判斷prevMsg是否爲null,prevMsg表示了當前要執行的消息msg的前一個消息,不爲null,表示msg是從隊列中間位置取出來的執行的,那麼這一步就得把隊列繼續鏈接起來。如果prevMsg爲null,也就是說msg是從隊列中的第一個位置取出的,只需要將mMessages變量重新指向msg的下一個消息就好了。
  7. 將要執行的消息msg的next屬性清空,然後返回。
  8. 如果出現了同步屏障,並且下一個異步消息也沒找到,那就是msg就是null 的,nextPollTimeoutMillis = -1,for循環的下次將會被阻塞住,這是個next()方法中的for死循環。
  9. 判斷是否要退出。主線程是不允許被退出的。
  10. 處理那些空閒的時候才處理的IdleHandler事件,然後結束之後,mBlocked被置爲true。也就是說當MessageQueue中沒有任何事情可做的時候,mBlocked纔是true。

上述就是MessageQueue的next()方法。經過該方法後繼續看Looper的loop()方法:

//Looper.java。
public static void loop() {
        //。。。省略代碼
        for (;;) {
            //。。。省略代碼
            try {
                //msg.target就是Handler,然後分發消息。
                msg.target.dispatchMessage(msg);
                end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
            } finally {
              //。。。省略日誌代碼
            }
           //。。。省略日誌代碼
            //消息處理結束之後回收消息。
            msg.recycleUnchecked();
        }
    }

這裏獲取到Message的target屬性,然後調用了dispatchMessage()方法。target屬性是在Handler的enqueueMessage()方法中賦值的:

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

也就是當前Handler對象。之後就是Handle的分發方法:

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

代碼一目瞭然。如果msg.callback不爲null,說明當前的消息是Runnable對象。不是的話,判斷mCallback是否爲null,也就是Handler的構造方法中的參數Callback,不爲null就調用Callback的handleMessage()方法。再接着就是調用自身的handleMessage()方法。到這Handle的源碼分析就結束了!重點難點全在MessageQueue類中。

好了,文章到這裏就結束瞭如果你覺得文章還算有用的話,不妨把它們推薦給你的朋友。

漫漫開發之路,我們只是其中的一小部分……只有不斷的學習、進階,纔是我們的出路!纔跟得上時代的進步!

今年年初我花一個月的時間收錄整理了一套知識體系,如果有想法深入的系統化的去學習的,可以私信我【學習】,我會把我收錄整理的資料都送給大家,幫助大家更快的進階。

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