Android Handler機(jī)制7之消息發(fā)送

Android Handler機(jī)制系列文章整體內(nèi)容如下:

本片文章的主要內(nèi)容如下:

  • 1、Handler發(fā)送消息
  • 2、Handler的send方案
  • 3、Handler的post方案

一 、Handler發(fā)送消息

大家平時(shí)發(fā)送消息主要是調(diào)用的兩大類方法
如下兩圖:


send方案.png
send方案.png

光看上面這些API你可能會(huì)覺(jué)得handler能法兩種消息,一種是Runnable對(duì)象,一種是message對(duì)象,這是直觀的理解,但其實(shí)post發(fā)出的Runnable對(duì)象最后都封裝成message對(duì)象了。

  • send方案發(fā)送消息(需要回調(diào)才能接收消息)
    • 1、sendMessage(Message) 立即發(fā)送Message到消息隊(duì)列
    • 2、sendMessageAtFrontOfQueue(Message) 立即發(fā)送Message到隊(duì)列,而且是放在隊(duì)列的最前面
    • 3、sendMessageAtTime(Message,long) 設(shè)置時(shí)間,發(fā)送Message到隊(duì)列
    • 4、sendMessageDelayed(Message,long) 延時(shí)若干毫秒后,發(fā)送Message到隊(duì)列
  • post方案 立即發(fā)送Message到消息隊(duì)列
    • 1、post(Runnable) 立即發(fā)送Message到消息隊(duì)列
    • 2、postAtFrontOfQueue(Runnable) 立即發(fā)送Message到隊(duì)列,而且是放在隊(duì)列的最前面
    • 3、postAtTime(Runnable,long) 設(shè)置時(shí)間,發(fā)送Message到隊(duì)列
    • 4、postDelayed(Runnable,long) 在延時(shí)若干毫秒后,發(fā)送Message到隊(duì)列

下面我們就先從send方案中的第一個(gè)sendMessage() 開(kāi)始源碼跟蹤下:

二、 Handler的send方案

我們以Handler的sendMessage(Message msg)為例子。

(一)、boolean sendMessage(Message msg)方法

代碼在Handler.java 505行

    /**
     * Pushes a message onto the end of the message queue after all pending messages
     * before the current time. It will be received in {@link #handleMessage},
     * in the thread attached to this handler.
     *  
     * @return Returns true if the message was successfully placed in to the 
     *         message queue.  Returns false on failure, usually because the
     *         looper processing the message queue is exiting.
     */
    public final boolean sendMessage(Message msg)
    {
        return sendMessageDelayed(msg, 0);
    }

老規(guī)矩先翻譯一下注釋:

在當(dāng)前時(shí)間,在所有待處理消息之后,將消息推送到消息隊(duì)列的末尾。在和當(dāng)前線程關(guān)聯(lián)的的Handler里面的handleMessage將收到這條消息,

我們看到sendMessage(Message)里面代碼很簡(jiǎn)單,就是調(diào)用了sendMessageDelayed(msg,0)

1、boolean sendMessageDelayed(Message msg, long delayMillis)

代碼在Handler.java 565行

    /**
     * Enqueue a message into the message queue after all pending messages
     * before (current time + delayMillis). You will receive it in
     * {@link #handleMessage}, in the thread attached to this handler.
     *  
     * @return Returns true if the message was successfully placed in to the 
     *         message queue.  Returns false on failure, usually because the
     *         looper processing the message queue is exiting.  Note that a
     *         result of true does not mean the message will be processed -- if
     *         the looper is quit before the delivery time of the message
     *         occurs then the message will be dropped.
     */
    public final boolean sendMessageDelayed(Message msg, long delayMillis)
    {
        if (delayMillis < 0) {
            delayMillis = 0;
        }
        return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
    }

注釋和boolean sendMessage(Message msg)方法差不多,我就不翻譯了

該方法內(nèi)部就做了兩件事

  • 1、判斷delayMillis是否小于0
  • 2、調(diào)用了public boolean sendMessageAtTime(Message msg, long uptimeMillis)方法
2、boolean sendMessageAtTime(Message msg, long uptimeMillis)

代碼在Handler.java 592行

    /**
     * Enqueue a message into the message queue after all pending messages
     * before the absolute time (in milliseconds) <var>uptimeMillis</var>.
     * <b>The time-base is {@link android.os.SystemClock#uptimeMillis}.</b>
     * Time spent in deep sleep will add an additional delay to execution.
     * You will receive it in {@link #handleMessage}, in the thread attached
     * to this handler.
     * 
     * @param uptimeMillis The absolute time at which the message should be
     *         delivered, using the
     *         {@link android.os.SystemClock#uptimeMillis} time-base.
     *         
     * @return Returns true if the message was successfully placed in to the 
     *         message queue.  Returns false on failure, usually because the
     *         looper processing the message queue is exiting.  Note that a
     *         result of true does not mean the message will be processed -- if
     *         the looper is quit before the delivery time of the message
     *         occurs then the message will be dropped.
     */
    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);
    }

老規(guī)矩先翻譯一下注釋:

以android系統(tǒng)的SystemClock的uptimeMillis()為基準(zhǔn),以毫秒為基本單位的絕對(duì)時(shí)間下,在所有待處理消息后,將消息放到消息隊(duì)列中。深度睡眠中的時(shí)間將會(huì)延遲執(zhí)行的時(shí)間,你將在和當(dāng)前線程辦的規(guī)定的Handler中的handleMessage中收到該消息。

這里順便提一下異步的作用,因?yàn)橥ǔN覀兝斫獾漠惒绞侵感麻_(kāi)一個(gè)線程,但是這里不是,因?yàn)楫惒降囊彩前l(fā)送到looper所綁定的消息隊(duì)列中,這里的異步主要是針對(duì)Message中的障柵(Barrier)而言的,當(dāng)出現(xiàn)障柵(Barrier)的時(shí)候,同步的會(huì)被阻塞,而異步的則不會(huì)。所以這個(gè)異步僅僅是一個(gè)標(biāo)記而已。

該方法內(nèi)部就做了兩件事

  • 1、獲取消息隊(duì)列,并對(duì)該消息隊(duì)列做非空判斷,如果為null,直接返回false,表示消息發(fā)送失敗
  • 2、調(diào)用了boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis)方法
3、boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis)

代碼在Handler.java 626行

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

本方法內(nèi)部做了三件事

  • 1、設(shè)置msg的target變量,并將target指向自己
  • 2、如果Handler的mAsynchronous值為true(默認(rèn)為false,即不設(shè)置),則設(shè)置msg的flags值,讓是否異步在Handler和Message達(dá)成統(tǒng)一。
  • 3、調(diào)用MessageQueue的enqueueMessage()方法
4、boolean enqueueMessage(Message msg, long when)方法

代碼在MessageQueue.java 533行

    boolean enqueueMessage(Message msg, long when) {
        //第一步
        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) {
             // 第四步
            //判斷消息隊(duì)列是否正在關(guān)閉
            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;
            Message p = mMessages;
            boolean needWake;
             // 第六步
            //根據(jù)when的比較來(lái)判斷要添加的Message是否應(yīng)該放在隊(duì)列頭部,當(dāng)?shù)谝粋€(gè)添加消息的時(shí)候,
            // 測(cè)試隊(duì)列為空,所以該Message也應(yīng)該位于頭部。
            if (p == null || when == 0 || when < p.when) {
                // New head, wake up the event queue if blocked.
                // 把msg的下一個(gè)元素設(shè)置為p
                msg.next = p;
                // 把msg設(shè)置為鏈表的頭部元素
                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.
                //除非消息隊(duì)列的頭部是障柵(barrier),或者消息隊(duì)列的第一個(gè)消息是異步消息,
                //否則如果是插入到中間位置,我們通常不喚醒消息隊(duì)列,
                 // 第八步
                needWake = mBlocked && p.target == null && msg.isAsynchronous();
                Message prev;
                  // 第九步
                 // 不斷遍歷消息隊(duì)列,根據(jù)when的比較找到合適的插入Message的位置。
                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;
    }

因?yàn)檫@是消息入隊(duì)的流程,為了讓大家更好的理解,我將上面的流程大致分為12步驟

  • 第1步驟、 判斷msg的target變量是否為null,如果為null,則為障柵(barrier),而障柵(barrier)入隊(duì)則是通過(guò)postSyncBarrier()方法入隊(duì),所以msg的target一定有值
  • 第2步驟、 判斷msg的標(biāo)志位,因?yàn)榇藭r(shí)的msg應(yīng)該是要入隊(duì),意味著msg的標(biāo)志位應(yīng)該顯示還未被使用。如果顯示已使用,明顯有問(wèn)題,直接拋異常。
  • 第3步驟、 加入同步鎖。
  • 第4步驟、 判斷消息隊(duì)列是否正在被關(guān)閉,如果是正在被關(guān)閉,則return false告訴消息入隊(duì)是失敗,并且回收消息
  • 第5步驟、 設(shè)置msg的when并且修改msg的標(biāo)志位,msg標(biāo)志位顯示為已使用
  • 第6步驟、 如果p==null則說(shuō)明消息隊(duì)列中的鏈表的頭部元素為null;when == 0 表示立即執(zhí)行;when< p.when 表示 msg的執(zhí)行時(shí)間早與鏈表中的頭部元素的時(shí)間,所以上面三個(gè)條件,那個(gè)條件成立,都要把msg設(shè)置成消息隊(duì)列中鏈表的頭部是元素
  • 第7步驟、 如果上面三個(gè)條件都不滿足則說(shuō)明要把msg插入到中間的位置,不需要插入到頭部
  • 第8步驟、 如果頭部元素不是障柵(barrier)或者異步消息,而且還是插入中間的位置,我們是不喚醒消息隊(duì)列的。
  • 第9步驟、 進(jìn)入一個(gè)死循環(huán),將p的值賦值給prev,前面的帶我們知道,p指向的是mMessage,所以這里是將prev指向了mMessage,在下一次循環(huán)的時(shí)候,prev則指向了第一個(gè)message,一次類推。接著講p指向了p.next也就是mMessage.next,也就是消息隊(duì)列鏈表中的第二個(gè)元素。這一步驟實(shí)現(xiàn)了消息指針的移動(dòng),此時(shí)p表示的消息隊(duì)列中第二個(gè)元素。
  • 第10步驟、 p==null,則說(shuō)明沒(méi)有下一個(gè)元素,即消息隊(duì)列到頭了,跳出循環(huán);p!=null&&when < p.when 則說(shuō)明當(dāng)前需要入隊(duì)的這個(gè)message的執(zhí)行時(shí)間是小于隊(duì)列中這個(gè)任務(wù)的執(zhí)行時(shí)間的,也就是說(shuō)這個(gè)需要入隊(duì)的message需要比隊(duì)列中這個(gè)message先執(zhí)行,則說(shuō)明這個(gè)位置剛剛是適合這個(gè)message的,所以跳出循環(huán)。 如果上面的兩個(gè)條件都不滿足,則說(shuō)明這個(gè)位置還不是放置這個(gè)需要入隊(duì)的message,則繼續(xù)跟鏈表中后面的元素,也就是繼續(xù)跟消息隊(duì)列中的下一個(gè)消息進(jìn)行對(duì)比,直到滿足條件或者到達(dá)隊(duì)列的末尾。
  • 第11步驟、 因?yàn)闆](méi)有滿足條件,說(shuō)明隊(duì)列中還有消息,不需要喚醒。
  • 第12步驟、 跳出循環(huán)后主要做了兩件事:事件A,將入隊(duì)的這個(gè)消息的next指向循環(huán)中獲取到的應(yīng)該排在這個(gè)消息之后message。事件B,將msg前面的message.next指向了msg。這樣就將一個(gè)message完成了入隊(duì)。
  • 第13步驟、 如果需要喚醒,則喚醒,具體請(qǐng)看后面的Handler中的Native詳解。
  • 第14步驟、 返回true,告知入隊(duì)成功。

提供兩張圖,讓大家更好的理解入隊(duì)


入隊(duì)1.png
入隊(duì)2.png

總結(jié)一句話就是:就是遍歷消息隊(duì)列中所有的消息,根據(jù)when的比較找到合適添加Message的位置。

上面是sendMessage(Message msg)發(fā)送消息機(jī)制,這樣再來(lái)看下其他的send方案

(二) boolean sendMessageAtFrontOfQueue(Message msg)

代碼在Handler.java 615行

    /**
     * Enqueue a message at the front of the message queue, to be processed on
     * the next iteration of the message loop.  You will receive it in
     * {@link #handleMessage}, in the thread attached to this handler.
     * <b>This method is only for use in very special circumstances -- it
     * can easily starve the message queue, cause ordering problems, or have
     * other unexpected side-effects.</b>
     *  
     * @return Returns true if the message was successfully placed in to the 
     *         message queue.  Returns false on failure, usually because the
     *         looper processing the message queue is exiting.
     */
    public final boolean sendMessageAtFrontOfQueue(Message msg) {
        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, 0);
    }

老規(guī)矩先翻譯一下注釋:

在消息隊(duì)列的最前面插入一個(gè)消息,在消息循環(huán)的下一次迭代中進(jìn)行處理。你將在當(dāng)前線程關(guān)聯(lián)的Handler的handleMessage()中收到這個(gè)消息。由于它可以輕松的解決消息隊(duì)列的排序問(wèn)題和其他的意外副作用。

方法內(nèi)部的實(shí)現(xiàn)和boolean sendMessageAtTime(Message msg, long uptimeMillis)大體上一致,唯一的區(qū)別就是該方法在調(diào)用enqueueMessage(MessageQueue, Message, long)方法的時(shí)候,最后一個(gè)參數(shù)是0而已。

(三) boolean sendEmptyMessage(int what)

代碼在Handler.java 517行

   /**
     * Sends a Message containing only the what value.
     *  
     * @return Returns true if the message was successfully placed in to the 
     *         message queue.  Returns false on failure, usually because the
     *         looper processing the message queue is exiting.
     */
    public final boolean sendEmptyMessage(int what)
    {
        return sendEmptyMessageDelayed(what, 0);
    }

老規(guī)矩先翻譯一下注釋:

發(fā)送一個(gè)僅有what的Message

內(nèi)容很簡(jiǎn)單,也就是調(diào)用sendEmptyMessageDelayed(int,long)而已,那么下面我們來(lái)看下sendEmptyMessageDelayed(int,long)的具體實(shí)現(xiàn)。

1、boolean sendEmptyMessageDelayed(int what, long delayMillis)

代碼在Handler.java 531行

    /**
     * Sends a Message containing only the what value, to be delivered
     * after the specified amount of time elapses.
     * @see #sendMessageDelayed(android.os.Message, long) 
     * 
     * @return Returns true if the message was successfully placed in to the 
     *         message queue.  Returns false on failure, usually because the
     *         looper processing the message queue is exiting.
     */
    public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
        Message msg = Message.obtain();
        msg.what = what;
        return sendMessageDelayed(msg, delayMillis);
    }

老規(guī)矩先翻譯一下注釋:

發(fā)送一個(gè)僅有what的Message,并且延遲特定的時(shí)間發(fā)送

這個(gè)方法內(nèi)部主要就是做了3件事

  • 1、調(diào)用Message.obtain();從消息對(duì)象池中獲取一個(gè)空的Message。
  • 2、設(shè)置這個(gè)Message的what值
  • 3、調(diào)用sendMessageDelayed(Message,long) 將這個(gè)消息方法

sendMessageDelayed(Message,long) 這個(gè)方法上面有講解過(guò),這里就不詳細(xì)說(shuō)了

(四) boolean sendEmptyMessageAtTime(int what, long uptimeMillis)

代碼在Handler.java 547行

    /**
     * Sends a Message containing only the what value, to be delivered 
     * at a specific time.
     * @see #sendMessageAtTime(android.os.Message, long)
     *  
     * @return Returns true if the message was successfully placed in to the 
     *         message queue.  Returns false on failure, usually because the
     *         looper processing the message queue is exiting.
     */

    public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) {
        Message msg = Message.obtain();
        msg.what = what;
        return sendMessageAtTime(msg, uptimeMillis);
    }

老規(guī)矩先翻譯一下注釋:

發(fā)送一個(gè)僅有what的Message,并且在特定的時(shí)間發(fā)送

這個(gè)方法內(nèi)部主要就是做了3件事

  • 1、調(diào)用Message.obtain();從消息對(duì)象池中獲取一個(gè)空的Message。
  • 2、設(shè)置這個(gè)Message的what值
  • 3、調(diào)用sendMessageAtTime(Message,long) 將這個(gè)消息方法

(五) 小結(jié)

綜上所述

  • public final boolean sendMessage(Message msg)
  • public final boolean sendEmptyMessage(int what)
  • public final boolean sendEmptyMessageDelayed(int what, long delayMillis)
  • public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis)
  • public final boolean sendMessageDelayed(Message msg, long delayMillis)
  • public boolean sendMessageAtTime(Message msg, long uptimeMillis)
  • public boolean sendMessageAtTime(Message msg, long uptimeMillis)
  • public final boolean sendMessageAtFrontOfQueue(Message msg)

以上這些send方案都會(huì)從這里或者那里最終走到boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis)如下圖

send小結(jié).png

三、 Handler的post方案

(一)、boolean post(Runnable r)方法

代碼在Handler.java 324行

    /**
     * Causes the Runnable r to be added to the message queue.
     * The runnable will be run on the thread to which this handler is 
     * attached. 
     *  
     * @param r The Runnable that will be executed.
     * 
     * @return Returns true if the Runnable was successfully placed in to the 
     *         message queue.  Returns false on failure, usually because the
     *         looper processing the message queue is exiting.
     */
    public final boolean post(Runnable r)
    {
       return  sendMessageDelayed(getPostMessage(r), 0);
    }

老規(guī)矩先翻譯一下注釋:

將一個(gè)Runnable添加到消息隊(duì)列中,這個(gè)runnable將會(huì)在和當(dāng)前Handler關(guān)聯(lián)的線程中被執(zhí)行。

這個(gè)方法內(nèi)部很簡(jiǎn)單,就是調(diào)用了sendMessageDelayed(Message, long);這個(gè)方法,所以可見(jiàn)boolean post(Runnable r)這個(gè)方法最終還是走到上面說(shuō)到的send的流程中,最終調(diào)用boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis)。

這里面調(diào)用了Message getPostMessage(Runnable r),我們來(lái)看一下。

1、Message getPostMessage(Runnable r)方法

代碼在Handler.java 725行

    private static Message getPostMessage(Runnable r) {
        Message m = Message.obtain();
        m.callback = r;
        return m;
    }

代碼很簡(jiǎn)單,主要是做了兩件事

  • 通過(guò)Message.obtain()從消息對(duì)象池中獲取一個(gè)空的Message
  • 將這空的Message的callback變量指向Runnable

最后返回這個(gè)Message m。

2、小結(jié)

所以我們知道boolean post(Runnable r)方法的內(nèi)置也是通過(guò)Message.obtain()來(lái)獲取一個(gè)Message對(duì)象m,然后僅僅把m的callback指向參數(shù)r而已。最后最終通過(guò)調(diào)用send方案的某個(gè)流程最終調(diào)用到boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis)

這時(shí)候聰明的同學(xué)一定會(huì)想,那么post方案的其他方法是不是也是這樣的?是的,的確都是這樣,這都是“套路”,那我們就用一一去檢驗(yàn)。

(二)、boolean postAtTime(Runnable r, long uptimeMillis)方法

代碼在Handler.java 347行

    /**
     * Causes the Runnable r to be added to the message queue, to be run
     * at a specific time given by <var>uptimeMillis</var>.
     * <b>The time-base is {@link android.os.SystemClock#uptimeMillis}.</b>
     * Time spent in deep sleep will add an additional delay to execution.
     * The runnable will be run on the thread to which this handler is attached.
     *
     * @param r The Runnable that will be executed.
     * @param uptimeMillis The absolute time at which the callback should run,
     *         using the {@link android.os.SystemClock#uptimeMillis} time-base.
     *  
     * @return Returns true if the Runnable was successfully placed in to the 
     *         message queue.  Returns false on failure, usually because the
     *         looper processing the message queue is exiting.  Note that a
     *         result of true does not mean the Runnable will be processed -- if
     *         the looper is quit before the delivery time of the message
     *         occurs then the message will be dropped.
     */
    public final boolean postAtTime(Runnable r, long uptimeMillis)
    {
        return sendMessageAtTime(getPostMessage(r), uptimeMillis);
    }

老規(guī)矩先翻譯一下注釋:

將一個(gè)Runnable添加到消息隊(duì)列中,這個(gè)runnable將會(huì)一個(gè)特定的時(shí)間被執(zhí)行,這個(gè)時(shí)間是以android.os.SystemClock.uptimeMillis()為基準(zhǔn)。如果在深度睡眠下,會(huì)推遲執(zhí)行的時(shí)間,這個(gè)Runnable將會(huì)在和當(dāng)前Hander關(guān)聯(lián)的線程中被執(zhí)行。

方法內(nèi)部也是先是調(diào)用getPostMessage(Runnable)來(lái)獲取一個(gè)Message,這個(gè)Message的callback字段指向了這個(gè)Runnable,然后調(diào)用sendMessageAtTime(Message,long)。

(三)、boolean postAtTime(Runnable r, Object token, long uptimeMillis)方法

代碼在Handler.java 372行

    /**
     * Causes the Runnable r to be added to the message queue, to be run
     * at a specific time given by <var>uptimeMillis</var>.
     * <b>The time-base is {@link android.os.SystemClock#uptimeMillis}.</b>
     * Time spent in deep sleep will add an additional delay to execution.
     * The runnable will be run on the thread to which this handler is attached.
     *
     * @param r The Runnable that will be executed.
     * @param uptimeMillis The absolute time at which the callback should run,
     *         using the {@link android.os.SystemClock#uptimeMillis} time-base.
     * 
     * @return Returns true if the Runnable was successfully placed in to the 
     *         message queue.  Returns false on failure, usually because the
     *         looper processing the message queue is exiting.  Note that a
     *         result of true does not mean the Runnable will be processed -- if
     *         the looper is quit before the delivery time of the message
     *         occurs then the message will be dropped.
     *         
     * @see android.os.SystemClock#uptimeMillis
     */
    public final boolean postAtTime(Runnable r, Object token, long uptimeMillis)
    {
        return sendMessageAtTime(getPostMessage(r, token), uptimeMillis);
    }

這個(gè)方法的翻譯同上,這個(gè)方法和上個(gè)方法唯一不同就是多了Object參數(shù),而這個(gè)參數(shù)僅僅是把Message.obtain();獲取的Message的obj字段的指向第二個(gè)入?yún)oken而已。最后也是調(diào)用sendMessageAtTime(Message,long)。

(四)、boolean postDelayed(Runnable r, long delayMillis)方法

代碼在Handler.java 396行

    /**
     * Causes the Runnable r to be added to the message queue, to be run
     * after the specified amount of time elapses.
     * The runnable will be run on the thread to which this handler
     * is attached.
     * <b>The time-base is {@link android.os.SystemClock#uptimeMillis}.</b>
     * Time spent in deep sleep will add an additional delay to execution.
     *  
     * @param r The Runnable that will be executed.
     * @param delayMillis The delay (in milliseconds) until the Runnable
     *        will be executed.
     *        
     * @return Returns true if the Runnable was successfully placed in to the 
     *         message queue.  Returns false on failure, usually because the
     *         looper processing the message queue is exiting.  Note that a
     *         result of true does not mean the Runnable will be processed --
     *         if the looper is quit before the delivery time of the message
     *         occurs then the message will be dropped.
     */
    public final boolean postDelayed(Runnable r, long delayMillis)
    {
        return sendMessageDelayed(getPostMessage(r), delayMillis);
    }

這個(gè)方法也很簡(jiǎn)單,就是依舊是通過(guò)getPostMessage(Runnable)來(lái)獲取一個(gè)Message,最后調(diào)用sendMessageDelayed(Message,long)而已。

(五)、boolean postDelayed(Runnable r, long delayMillis)方法

代碼在Handler.java 416行

    /**
     * Posts a message to an object that implements Runnable.
     * Causes the Runnable r to executed on the next iteration through the
     * message queue. The runnable will be run on the thread to which this
     * handler is attached.
     * <b>This method is only for use in very special circumstances -- it
     * can easily starve the message queue, cause ordering problems, or have
     * other unexpected side-effects.</b>
     *  
     * @param r The Runnable that will be executed.
     * 
     * @return Returns true if the message was successfully placed in to the 
     *         message queue.  Returns false on failure, usually because the
     *         looper processing the message queue is exiting.
     */
    public final boolean postAtFrontOfQueue(Runnable r)
    {
        return sendMessageAtFrontOfQueue(getPostMessage(r));
    }

這個(gè)方法也很簡(jiǎn)單,就是依舊是通過(guò)getPostMessage(Runnable)來(lái)獲取一個(gè)Message,最后調(diào)用sendMessageAtFrontOfQueue(Message)而已。

(六)、小結(jié)

Handler的post方案的如下方法

  • boolean post(Runnable r)
  • postAtTime(Runnable r, long uptimeMillis)
  • boolean postAtTime(Runnable r, Object token, long uptimeMillis)
  • boolean postDelayed(Runnable r, long delayMillis)
  • boolean postAtFrontOfQueue(Runnable r)
    都是通過(guò)Message getPostMessage(Runnable )中調(diào)用Message m = Message.obtain();來(lái)獲取一個(gè)空的Message,然后把這個(gè)Message的callback變量指向了Runnable,最終調(diào)用相應(yīng)的send方案而已。

所以我們可以這樣說(shuō):

Handler的發(fā)送消息(障柵除外),無(wú)論是通過(guò)send方案還是pos方案最終都會(huì)做走到 boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis)
消息發(fā)送.png
最后編輯于
?著作權(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)容