Android中的Handler機(jī)制

  • 一、Handler概述
  • 二、Handler發(fā)送消息的方法
  • 三、MessageQueue的enqueueMessage()
  • 四、Message的when字段
  • 五、子線程中使用Handler
  • 六、Looper.loop()
  • 七、獲取下一個(gè)消息MessageQueue的next()
  • 八、Handler的dispatchMesssage()

Handler在native層還有很多知識(shí)點(diǎn),這篇主要圍繞java層。

一、Handler概述

1. 什么是Handler?

Handler可以將一個(gè)任務(wù)切換到指定線程中執(zhí)行,常用來(lái)實(shí)現(xiàn)在子線程工作完后切換到UI線程更新UI。

在ViewRootImpl中的checkThread()會(huì)檢查當(dāng)前線程,在更新UI時(shí)會(huì)調(diào)用到這個(gè)方法,所以在非UI線程中執(zhí)行UI操作就會(huì)拋出此異常。

void checkThread() {
    if (mThread != Thread.currentThread()) {
        throw new CalledFromWrongThreadException(
                "Only the original thread that created a view hierarchy can touch its views.");
    }
}

UI控件不是線程安全的,多線程并發(fā)訪問(wèn)就會(huì)出現(xiàn)問(wèn)題,所以只允許在主線程更新UI。之所以UI控件沒(méi)有考慮上鎖保證線程安全,是因?yàn)樯湘i會(huì)讓代碼邏輯變得復(fù)雜且會(huì)降低UI訪問(wèn)的效率。

2. Handler底層

Handler的運(yùn)行需要底層的MessageQueue、Message和Looper來(lái)支撐。

a. MessageQueue

  • MessageQueue是消息隊(duì)列。
  • 采用單鏈表的形式存儲(chǔ)消息列表。
  • 向外提供對(duì)Message的插入和刪除工作。

b. Message

  • 消息實(shí)體。

c. Looper

  • Handler創(chuàng)建的時(shí)候采用當(dāng)前線程的Looper來(lái)構(gòu)造消息循環(huán)系統(tǒng)。
  • Looper以無(wú)限循環(huán)的形式查看是否有新消息。
  • 有新消息時(shí),就將Message對(duì)象從MessageQueue中取出,并將其交給Handler的dispatchMessage()。
  • Looper屬于單個(gè)線程實(shí)例,通過(guò)ThreadLocal獲得。

ThreadLocal可以在不同的線程中互不干擾地存儲(chǔ)并提供數(shù)據(jù),通過(guò)ThreadLocal可以很輕松地獲取每個(gè)線程的Looper。

  • 線程中默認(rèn)是沒(méi)有Looper的,如果需要,就要為線程創(chuàng)建Looper。
  • 主線程在ActivtyThread創(chuàng)建時(shí)會(huì)初始化Looper,所以主線程默認(rèn)可以使用Handler。

3. Handler工作步驟

  1. Handler創(chuàng)建,采用當(dāng)前線程的Looper構(gòu)建內(nèi)部消息系統(tǒng)。
  2. Handler的post()、send()等方法調(diào)用MessageQueue的enqueueMessage()將一個(gè)Message加入到消息隊(duì)列。
  3. Looper發(fā)現(xiàn)新消息的到來(lái),處理這個(gè)消息。


二、Handler發(fā)送消息的方法

發(fā)送消息的方法比較多,主要可以分為兩類,一類sendXXXX(),一類postXxxx(),兩類的主要區(qū)別就是send系的主要接受一個(gè)Message對(duì)象,而post系的主要接收一個(gè)Runnable對(duì)象,但最終也是封裝成了Message對(duì)象。


boolean sendMessage(Message msg)
public final boolean sendMessage(Message msg)
{
    return sendMessageDelayed(msg, 0);
}
boolean sendMessageDelayed(Message msg, long delayMillis)
public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
    if (delayMillis < 0) {
        delayMillis = 0;
    }
    return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
boolean sendMessageAtTime(Message msg, long uptimeMillis)
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);
}

最后調(diào)用到MessageQueue的enqueueMessage()。

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

上面三個(gè)send系的方法最終都是調(diào)用了MessageQueue的enqueueMessage(),出入了Message對(duì)象和執(zhí)行時(shí)間。

boolean sendEmptyMessageDelayed(int what, long delayMillis)

sendEmptyMessage()系列的方法和上述方法類似,只是不需要傳入一個(gè)Message,Message在方法中默認(rèn)構(gòu)造了。

public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
    Message msg = Message.obtain();
    msg.what = what;
    return sendMessageDelayed(msg, delayMillis);
}

再來(lái)看post系的方法。

boolean post(Runnable r)
public final boolean post(Runnable r)
{
   return  sendMessageDelayed(getPostMessage(r), 0);
}

雖然傳入的是Runnable對(duì)象,但是在方法調(diào)用過(guò)程中同樣構(gòu)造了Message,調(diào)用了send的方法,所以最終也是通過(guò)Message對(duì)象的形式交給MessageQueue的enqueueMessage()的。

private static Message getPostMessage(Runnable r) {
    Message m = Message.obtain();
    m.callback = r;
    return m;
}
boolean postDelayed(Runnable r, long delayMillis)

postDelay()也同樣是構(gòu)造了Message對(duì)象,調(diào)用了sendMessageDelayed(),最終傳遞給MessageQueue的。

public final boolean postDelayed(Runnable r, long delayMillis) {
    return sendMessageDelayed(getPostMessage(r), delayMillis);
}

三、MessageQueue的enqueueMessage()

在Handler的enqueueMessage()中,賦值了Message對(duì)象的target屬性為執(zhí)行的Handler對(duì)象,之后就調(diào)用了MessageQueue的enqueueMessage()。

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

MessageQueue的enqueueMessage()還是比較長(zhǎng)的。

  1. 第一步是一些異常處理,先判斷msg的target是否為空、判斷msg是否正在使用,這個(gè)是否正在使用是在下面同步代碼塊中進(jìn)行賦值的。
  2. 進(jìn)入同步代碼塊了,判斷如果該msg已經(jīng)調(diào)用了quit()邊不再繼續(xù),直接回收返回。
  3. 進(jìn)行了一些賦值操作后就開(kāi)始加隊(duì)列的工作了。
  4. 首先如果隊(duì)列中還沒(méi)有Message或該Message執(zhí)行時(shí)間為0或是小于隊(duì)列中的第一個(gè)Message的時(shí)間,就將該Message作為隊(duì)列的頭,并更新頭Message記錄。
  5. 否則遍歷隊(duì)列,將Message插入到合適的位置,可以看出整個(gè)隊(duì)列是按Message的when(一個(gè)相對(duì)時(shí)間,表示執(zhí)行時(shí)間)字段從小到大排列的,如果兩個(gè)Mssage的when字段相同,則先入隊(duì)列的排在前面。
  6. 最后,如果需要喚醒MesssageQueue的next()就喚醒(MessageQueue的next()在沒(méi)有消息的時(shí)候會(huì)阻塞,而一旦添加了新消息,enqueueMessage()被調(diào)用,自然就喚醒了next())。
boolean enqueueMessage(Message msg, long when) {
    // 1.
    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) {
        // 2.
        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;
        }
        
        //3.
        msg.markInUse();
        msg.when = when;
        Message p = mMessages;
        boolean needWake;
        
        // 4.
        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 {
            // 5.
            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;
        }
        
        // 6.
        if (needWake) {
            // 此處喚醒next()。
            nativeWake(mPtr);
        }
    }
    return true;
}

四、Message的when字段

上面我們通過(guò)分析MessageQueue的enqueueMessage(),知道了Message隊(duì)列是按照Message對(duì)象的when字段去排列的,那么when字段是什么呢?

在Handler的sendMessageDelayed中可以看到Message對(duì)象的when字段是如何初始化的。when的值是SystemClock.uptimeMillis() + delayMillis。

public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
    if (delayMillis < 0) {
        delayMillis = 0;
    }
    return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}

SystemClock#uptimeMillis()表示當(dāng)前時(shí)間的一個(gè)相對(duì)時(shí)間,代表自系統(tǒng)啟動(dòng)開(kāi)始從到調(diào)用該方法時(shí)度過(guò)的毫秒數(shù)。加上傳參設(shè)置的delayMillis,整個(gè)when表示的時(shí)間代表該Message期望被分發(fā)的相對(duì)時(shí)間。

提供時(shí)間獲取的方法有很多,為什么要用該系統(tǒng)啟動(dòng)到調(diào)用方法的相對(duì)時(shí)間,而不用System.currentTimeMillis()呢,是因?yàn)樗淼氖菑?970-01-01 00:00:00到當(dāng)前時(shí)間的毫秒數(shù),這個(gè)值是一個(gè)強(qiáng)關(guān)聯(lián)系統(tǒng)時(shí)間,我們可以通過(guò)修改系統(tǒng)時(shí)間達(dá)到修改該值的目的,所以該值是不可靠的值,會(huì)有可能導(dǎo)致延時(shí)消息失效。when字段只是用時(shí)間差來(lái)表示先后關(guān)系,所以只需要一個(gè)相對(duì)時(shí)間就可以達(dá)成目的。

五、子線程中使用Handler

在UI線程中,Looper早已在app啟動(dòng)過(guò)程中就為我們初始化好了,所以可以直接獲取Handler對(duì)象并使用,但是在子線程中,必須手動(dòng)去初始化Looper,之后將Handler綁定該子線程的Looper才能夠使用。

Looper.prepare(); // 為子線程創(chuàng)建一個(gè)Looper
mHandler = new Handler(){ 
    @Override 
    public void handleMessage(Message msg) { 
        Log.d(TAG, "子線程的Handler"); 
    } 
}; 
mHandler.sendEmptyMessage(1);
Looper.loop();// 開(kāi)始循環(huán)

可以向上面一樣寫(xiě),這里面有一些注意點(diǎn)。

  • 在調(diào)用Handler之前必須調(diào)用Looper.prepare()方法,在當(dāng)前線程中創(chuàng)建一個(gè)looper。我們也可以直接使用HandlerThread,其中是帶有Looper的。
  • Looper.loop()是無(wú)限循環(huán)的,所以在Looper.loop()后邊的程序代碼塊是無(wú)法執(zhí)行到的。loop()方法的主要作用是一直不斷的通過(guò)queue.next()方法來(lái)讀取來(lái)自messagequeue中的msg,這個(gè)方法是block的狀態(tài),如果queue中沒(méi)有消息的話會(huì)一直阻塞在這里。

除了上面的寫(xiě)法,也可以在Handler構(gòu)造函數(shù)傳入Looper對(duì)象來(lái)綁定。

Handler handler = new Handler(looper);

上面兩種綁定Looper的方法中,第二種很直觀通過(guò)傳參綁定了,那么第一種方法是如何綁定的呢?

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

看到這里調(diào)用了Looper的myLooper(),猜想就是利用了ThreadLocal獲取到當(dāng)前線程的Looper對(duì)象了。

public Handler(Callback callback, boolean async) {
    // ......
    mLooper = Looper.myLooper();
    // ......
}

果然是調(diào)用了TreadLocal對(duì)象的get,該ThreadLocal對(duì)象泛型是Looper的。

static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
public static @Nullable Looper myLooper() {
    return sThreadLocal.get();
}

在Looper的prepare()中對(duì)該ThreadLocal放入了Looper對(duì)象,所以在使用Handler之前要先調(diào)用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));
}

六、Looper.loop()

Looper.loop()
  1. 獲取Looper對(duì)象并判空,再獲取MessageQueue對(duì)象。
  2. 進(jìn)入主循環(huán),調(diào)用MessageQueue的next()去獲取下一個(gè)消息,如果沒(méi)有消息就一直阻塞。
  3. 如果返回消息為null,直接return,此時(shí)說(shuō)明整個(gè)系統(tǒng)要處于退出狀態(tài)了。
  4. 如果獲取到了,就調(diào)用msg的Handler的dispatchMessage()執(zhí)行消息。
  5. 之后將msg放入回收池中等待復(fù)用。
  6. 繼續(xù)主循環(huán),循環(huán)上述步驟,一直到退出。
public static void loop() {
    // 獲取looper對(duì)象
    final Looper me = myLooper();
    // 判空異常
    if (me == null) {
        throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
    }
    // 獲取looper的MessageQueue
    final MessageQueue queue = me.mQueue;
    
    Binder.clearCallingIdentity();
    final long ident = Binder.clearCallingIdentity();
    
    // 開(kāi)始死循環(huán),不停獲取消息隊(duì)列中的消息并執(zhí)行
    for (;;) {
        // 調(diào)用MessageQueue的next()獲取新消息,這里可能被阻塞。
        Message msg = queue.next(); // might block
        // 如果返回了null,那么就說(shuō)明MessageQueue已經(jīng)quit了
        if (msg == null) {
            // No message indicates that the message queue is quitting.
            return;
        }
        
        // ...... 日志輸出等
        
        try {
            // 調(diào)用msg的Handler對(duì)象的dispatchMessage()去執(zhí)行消息。
            msg.target.dispatchMessage(msg);
            end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
        } finally {
            if (traceTag != 0) {
                Trace.traceEnd(traceTag);
            }
        }
        
        // ...... 日志輸出等
        
        // 將此msg放入回收對(duì)象池中,obtain()就是去復(fù)用這些對(duì)象。
        msg.recycleUnchecked();
    }
}

loop()不會(huì)自動(dòng)退出,Looper#quit() 或者 Looper#quitSafely() 讓它退出。兩個(gè)方法都調(diào)用了MessageQueue#quit(boolean)方法,當(dāng)MessageQueue#next()方法發(fā)現(xiàn)已經(jīng)調(diào)用過(guò) MessageQueue#quit(boolean)時(shí)會(huì)return null結(jié)束當(dāng)前調(diào)用,否則的話即使MessageQueue 已經(jīng)是空的了也會(huì)阻塞等待。

Q:既然是一個(gè)死循環(huán),那為什么沒(méi)有阻塞主線程呢?

如果說(shuō)操作系統(tǒng)是由中斷驅(qū)動(dòng)的,那么Android的應(yīng)用在宏觀上可以說(shuō)是 Handler機(jī)制驅(qū)動(dòng)的,所以主線程中的 Looper不會(huì)一直阻塞的,原因如下:

  • 當(dāng)隊(duì)列中只有延遲消息的時(shí)候,阻塞的時(shí)間等于頭結(jié)點(diǎn)的 when 減去 當(dāng)前時(shí)間,時(shí)間到了以后會(huì)自動(dòng)喚醒。
  • 在Android中 一個(gè)進(jìn)程中不會(huì)只有一個(gè)線程,由于 Handler 的機(jī)制,導(dǎo)致我們?nèi)绻僮?View 等都要通過(guò) Handler 將事件發(fā)送到主線程中去,所以會(huì)喚醒阻塞。
  • 傳感器的事件,如:觸摸事件、鍵盤(pán)輸入等。
  • 繪制事件:我們知道要想顯示流暢那么屏幕必須保持60fps的刷新率,那繪制事件在入隊(duì)列時(shí)也會(huì)喚醒。

更多的知識(shí)Android中為什么主線程不會(huì)因?yàn)長(zhǎng)ooper.loop()里的死循環(huán)卡死?

七、獲取下一個(gè)消息MessageQueue的next()

MessgaeQueue # next()

這個(gè)方法可能是Handler機(jī)制中最長(zhǎng)知識(shí)點(diǎn)最多的方法了,被上面的loop()調(diào)用,來(lái)獲取下一個(gè)Message對(duì)象。

  1. 處理已經(jīng)取消的情況。
  2. 進(jìn)入循環(huán)調(diào)用nativePollOnce(),如果沒(méi)有消息,就阻塞,如果有消息就繼續(xù)。
  3. 獲取第一個(gè)消息,如果第一個(gè)消息是barrier,就遍歷去獲取第一個(gè)異步消息。

enqueueMessage()會(huì)判斷target不為空,barrier消息是在postSyncBarrier()中添加的,而異步消息是在Handler構(gòu)造函數(shù)中指定的該Handlerf發(fā)送的消息是否為異步的。

  1. 如果消息時(shí)間到了就整理隊(duì)列并返回該消息,如果每到就更新時(shí)間點(diǎn)。
  2. 如果此為第一遍循環(huán),就去執(zhí)行idleHandler。執(zhí)行完之后復(fù)制變量讓下一次循環(huán)不再執(zhí)行此條。
Message next() {
    // 處理Looper已經(jīng)取消的情況,調(diào)用disposed()方法后mPtr=0
    final long ptr = mPtr;
    if (ptr == 0) {
        return null;
    }
    // 記錄空閑時(shí)需要處理的IdleHandler的數(shù)量。
    int pendingIdleHandlerCount = -1; // -1 only during first iteration
    // 表示距離處理下一個(gè)消息的時(shí)間,只要大于0就表明還有消息等待處理
    int nextPollTimeoutMillis = 0;
    
    for (;;) {
        if (nextPollTimeoutMillis != 0) {
           // 刷新Binder命令
           Binder.flushPendingCommands();
        }
        
        // 調(diào)用native層,如果返回了就說(shuō)明可以從隊(duì)列中取出一條消息,如果消息隊(duì)列中沒(méi)有消息就阻塞等待
        // 靠enqueueMessage()中最后一步調(diào)用nativeWake(mPtr)來(lái)喚醒該方法
        nativePollOnce(ptr, nextPollTimeoutMillis);
        
        // 上鎖
        synchronized (this) {
            // 獲取開(kāi)機(jī)到現(xiàn)在的時(shí)間
            final long now = SystemClock.uptimeMillis();
            Message prevMsg = null;
            // 表頭第一個(gè)消息
            Message msg = mMessages;
            
            // 判斷該Messagehi否是barrier
            if (msg != null && msg.target == null) {
                
                // 循環(huán)遍歷出第一個(gè)異步消息,如果設(shè)置了barrier,就不能再執(zhí)行同步消息了,除非將barrier移除。
                // 但是異步消息不受影響照樣執(zhí)行,所以在這里要找到異步消息
                do {
                    prevMsg = msg;
                    msg = msg.next;
                    // msg為null說(shuō)明已經(jīng)退出循環(huán),為異步消息則消息為要找的
                } while (msg != null && !msg.isAsynchronous());
            }
            
            if (msg != null) {
                // 如果分發(fā)時(shí)間還沒(méi)到
                if (now < msg.when) {
                    // Next message is not ready.  Set a timeout to wake up when it is ready.
                    // 更新執(zhí)行時(shí)間點(diǎn)
                    nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
                } else {
                    // 如果時(shí)間到了
                    // Got a message.
                    mBlocked = false;
                    // 處理消息隊(duì)列
                    if (prevMsg != null) {
                        prevMsg.next = msg.next;
                    } else {
                        mMessages = msg.next;
                    }
                    msg.next = null;
                    if (DEBUG) Log.v(TAG, "Returning message: " + msg);
                    // 標(biāo)記msg正在使用
                    msg.markInUse();
                    return msg;
                }
            } else {
                // 進(jìn)此處是msg==null,再?zèng)]有其它消息了
                // No more messages.
                nextPollTimeoutMillis = -1;
            }
            // Process the quit message now that all pending messages have been handled.
            // 正在退出了,返回null。
            if (mQuitting) {
                dispose();
                // 返回null,通知looper也停止
                return null;
            }
            
            // 判斷如果這是第一次循環(huán)(只有第一次循環(huán)時(shí)會(huì)小于0)并且隊(duì)列為空或還沒(méi)到處理第一個(gè)的時(shí)間
            if (pendingIdleHandlerCount < 0
                    && (mMessages == null || now < mMessages.when)) {
                pendingIdleHandlerCount = mIdleHandlers.size();
            }
            if (pendingIdleHandlerCount <= 0) {
                // No idle handlers to run.  Loop and wait some more.
                // 置為阻塞狀態(tài)
                mBlocked = true;
                continue;
            }
            // 初始化最少四個(gè)要被執(zhí)行的IdleHandler
            if (mPendingIdleHandlers == null) {
                mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
            }
            mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
        }
        
        // 開(kāi)始循環(huán)執(zhí)行所有的IdleHandler并根據(jù)返回值判斷是否保留
        for (int i = 0; i < pendingIdleHandlerCount; i++) {
            final IdleHandler idler = mPendingIdleHandlers[i];
            mPendingIdleHandlers[i] = null; // release the reference to the handler
            boolean keep = false;
            try {
                keep = idler.queueIdle();
            } catch (Throwable t) {
                Log.wtf(TAG, "IdleHandler threw exception", t);
            }
            if (!keep) {
                synchronized (this) {
                    mIdleHandlers.remove(idler);
                }
            }
        }
        
        // IdleHandler只會(huì)在消息隊(duì)列阻塞之前執(zhí)行一次,之后再不會(huì)執(zhí)行,知道下一次被調(diào)用next()。
        pendingIdleHandlerCount = 0;
        
        // 當(dāng)執(zhí)行了IdleHandler后,會(huì)消耗一段時(shí)間,刺死可能已經(jīng)到達(dá)執(zhí)行消息的時(shí)間了,所以重置該變量再重新檢查時(shí)間。
        nextPollTimeoutMillis = 0;
    }
}

八、Handler的dispatchMesssage()

在Looper的loop()中會(huì)調(diào)用該方法去處理msg,其實(shí)是一個(gè)分發(fā)過(guò)程。

msg.target.dispatchMessage(msg);

這里調(diào)用了target的方法,target字段是在Handler的enqueueMessage()中賦值的,為其Handler對(duì)象。這里調(diào)用了dispatchMessage()。

  1. 首先看msg中有沒(méi)有callback對(duì)象,如果有,就交給callback執(zhí)行。
  2. 如果沒(méi)有再看有沒(méi)有全局callback對(duì)象,如果有,就交給全局callback處理。
  3. 如果都沒(méi)有或者全局callback處理不了,再調(diào)用handleMessage()。
public void dispatchMessage(Message msg) {
    if (msg.callback != null) {
        handleCallback(msg);
    } else {
        if (mCallback != null) {
            if (mCallback.handleMessage(msg)) {
                return;
            }
        }
        handleMessage(msg);
    }
}

這里的一系列優(yōu)先級(jí)讓我想起了View的事件分發(fā)。
首先判斷的msg.callbck是調(diào)用post系方法時(shí)傳入的runnable,這個(gè)執(zhí)行的優(yōu)先級(jí)最高。

private static void handleCallback(Message message) {
    message.callback.run();
}

再就是判斷mCallback,這個(gè)callback是在某些帶有Callback參數(shù)的Handler構(gòu)造函數(shù)中傳入的。

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

當(dāng)然了,這個(gè)runnable完全可以返回false,設(shè)計(jì)在個(gè)人,如果想讓這個(gè)msg還有機(jī)會(huì)交給Handler的handleMessage()去處理,就讓它在合適的情況返回false。

最終到達(dá)handleMessage(),這個(gè)優(yōu)先級(jí)最低了。

public void handleMessage(Message msg) {
}

我們最常用的就是在定義Handler對(duì)象時(shí)重寫(xiě)這個(gè)方法添加自己的邏輯。

?著作權(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)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • 【Android Handler 消息機(jī)制】 前言 在Android開(kāi)發(fā)中,我們都知道不能在主線程中執(zhí)行耗時(shí)的任務(wù)...
    Rtia閱讀 5,084評(píng)論 1 28
  • Android中Handler機(jī)制介紹以及分析分為下面幾個(gè)部分闡述 Handler的介紹和作用 Handler的使...
    evil_ice閱讀 1,251評(píng)論 0 10
  • Handler機(jī)制在Android多線程編程中可以說(shuō)是不可或缺的角色,也是必須掌握的內(nèi)容,所以深入掌握并應(yīng)用Han...
    axiaochao閱讀 378評(píng)論 0 0
  • Android中的消息機(jī)制,消息的發(fā)送和接收過(guò)程以及與線程之間的關(guān)系。雖然我們經(jīng)常使用這些基礎(chǔ)的東西,但對(duì)于其內(nèi)部...
    Sunny君907閱讀 703評(píng)論 0 1
  • 1. ANR異常 Application No Response:應(yīng)用程序無(wú)響應(yīng)。在主線程中,是不允許執(zhí)行耗時(shí)的操...
    JackChen1024閱讀 1,595評(píng)論 0 3

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