Android Handler機(jī)制5--消息發(fā)送

移步Android Handler機(jī)制詳解

  • 1沙峻、Handler發(fā)送消息
  • 2屏鳍、Handler的send方案
  • 3悯森、Handler的post方案

1 Handler發(fā)送消息

send方案.png

post方案.png
  • send方案發(fā)送消息(需要回調(diào)才能接收消息)
  1. sendMessage(Message) 立即發(fā)送Message到消息隊(duì)列
  2. sendMessageAtFrontOfQueue(Message) 立即發(fā)送Message到隊(duì)列盅蝗,而且是放在隊(duì)列的最前面
  3. sendMessageAtTime(Message,long) 設(shè)置時間,發(fā)送Message到隊(duì)列
  4. sendMessageDelayed(Message,long) 延時若干毫秒后呢袱,發(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è)置時間,發(fā)送Message到隊(duì)列
  4. postDelayed(Runnable,long) 在延時若干毫秒后羞福,發(fā)送Message到隊(duì)列

2 Handler的send方案

以Handler的sendMessage(Message msg)為例子

2.1 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);
    }
  • 在當(dāng)前時間惕蹄,在所有待處理消息之后,將消息推送到消息隊(duì)列的末尾坯临。在和當(dāng)前線程關(guān)聯(lián)的的Handler里面的handleMessage將收到這條消息

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

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

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

2.1.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);
    }
  • 以android系統(tǒng)的SystemClock的uptimeMillis()為基準(zhǔn)看靠,以毫秒為基本單位的絕對時間下赶促,在所有待處理消息后,將消息放到消息隊(duì)列中挟炬。
  • 深度睡眠中的時間將會延遲執(zhí)行的時間鸥滨,你將在和當(dāng)前線程辦的規(guī)定的Handler中的handleMessage中收到該消息。
  • 因?yàn)橥ǔN覀兝斫獾漠惒绞侵感麻_一個線程谤祖,但是這里不是婿滓,因?yàn)楫惒降囊彩前l(fā)送到looper所綁定的消息隊(duì)列中,這里的異步主要是針對Message中的障柵(Barrier)而言的粥喜,當(dāng)出現(xiàn)障柵(Barrier)的時候凸主,同步的會被阻塞,而異步的則不會额湘。所以這個異步僅僅是一個標(biāo)記而已卿吐。

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

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

2.1.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指向自己
    1. 如果Handler的mAsynchronous值為true(默認(rèn)為false,即不設(shè)置)婆咸,則設(shè)置msg的flags值竹捉,讓是否異步在Handler和Message達(dá)成統(tǒng)一。
    1. 調(diào)用MessageQueue的enqueueMessage()方法

2.1.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的比較來判斷要添加的Message是否應(yīng)該放在隊(duì)列頭部擅耽,當(dāng)?shù)谝粋€添加消息的時候活孩,
            // 測試隊(duì)列為空物遇,所以該Message也應(yīng)該位于頭部乖仇。
            if (p == null || when == 0 || when < p.when) {
                // New head, wake up the event queue if blocked.
                // 把msg的下一個元素設(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ì)列的第一個消息是異步消息乃沙,
                //否則如果是插入到中間位置,我們通常不喚醒消息隊(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;
    }
  • 第1步驟眶根、 判斷msg的target變量是否為null蜀铲,如果為null,則為障柵(barrier)属百,而障柵(barrier)入隊(duì)則是通過postSyncBarrier()方法入隊(duì)记劝,所以msg的target一定有值
  • 第2步驟、 判斷msg的標(biāo)志位族扰,因?yàn)榇藭r的msg應(yīng)該是要入隊(duì)厌丑,意味著msg的標(biāo)志位應(yīng)該顯示還未被使用。如果顯示已使用渔呵,明顯有問題怒竿,直接拋異常。
  • 第3步驟扩氢、 加入同步鎖耕驰。
  • 第4步驟、 判斷消息隊(duì)列是否正在被關(guān)閉录豺,如果是正在被關(guān)閉朦肘,則return false告訴消息入隊(duì)是失敗托嚣,并且回收消息
  • 第5步驟、 設(shè)置msg的when并且修改msg的標(biāo)志位厚骗,msg標(biāo)志位顯示為已使用
  • 第6步驟示启、 如果p==null則說明消息隊(duì)列中的鏈表的頭部元素為null;when == 0 表示立即執(zhí)行领舰;when< p.when 表示 msg的執(zhí)行時間早與鏈表中的頭部元素的時間夫嗓,所以上面三個條件,那個條件成立冲秽,都要把msg設(shè)置成消息隊(duì)列中鏈表的頭部是元素
  • 第7步驟舍咖、 如果上面三個條件都不滿足則說明要把msg插入到中間的位置,不需要插入到頭部
  • 第8步驟锉桑、 如果頭部元素不是障柵(barrier)或者異步消息排霉,而且還是插入中間的位置,我們是不喚醒消息隊(duì)列的民轴。
  • 第9步驟攻柠、 進(jìn)入一個死循環(huán),將p的值賦值給prev后裸,前面的帶我們知道瑰钮,p指向的是mMessage,所以這里是將prev指向了mMessage微驶,在下一次循環(huán)的時候浪谴,prev則指向了第一個message,一次類推因苹。接著講p指向了p.next也就是mMessage.next苟耻,也就是消息隊(duì)列鏈表中的第二個元素。這一步驟實(shí)現(xiàn)了消息指針的移動扶檐,此時p表示的消息隊(duì)列中第二個元素凶杖。
  • 第10步驟、 p==null蘸秘,則說明沒有下一個元素官卡,即消息隊(duì)列到頭了,跳出循環(huán)醋虏;p!=null&&when < p.when 則說明當(dāng)前需要入隊(duì)的這個message的執(zhí)行時間是小于隊(duì)列中這個任務(wù)的執(zhí)行時間的寻咒,也就是說這個需要入隊(duì)的message需要比隊(duì)列中這個message先執(zhí)行,則說明這個位置剛剛是適合這個message的颈嚼,所以跳出循環(huán)毛秘。 如果上面的兩個條件都不滿足,則說明這個位置還不是放置這個需要入隊(duì)的message,則繼續(xù)跟鏈表中后面的元素叫挟,也就是繼續(xù)跟消息隊(duì)列中的下一個消息進(jìn)行對比艰匙,直到滿足條件或者到達(dá)隊(duì)列的末尾。
  • 第11步驟抹恳、 因?yàn)闆]有滿足條件员凝,說明隊(duì)列中還有消息,不需要喚醒奋献。
  • 第12步驟健霹、 跳出循環(huán)后主要做了兩件事:事件A,將入隊(duì)的這個消息的next指向循環(huán)中獲取到的應(yīng)該排在這個消息之后message瓶蚂。事件B糖埋,將msg前面的message.next指向了msg。這樣就將一個message完成了入隊(duì)窃这。
  • 第13步驟瞳别、 如果需要喚醒,則喚醒杭攻,具體請看后面的Handler中的Native詳解祟敛。
  • 第14步驟、 返回true朴上,告知入隊(duì)成功垒棋。

插入消息后,有條件地執(zhí)行nativeWake去喚醒epoll痪宰。needWake的值依賴mBlocked——當(dāng)進(jìn)入next()方法時沒有待處理的消息,mBlock為true畔裕,有消息并返回到looper時衣撬,mBlock為false。

結(jié)合next()和enqueueMessage()方法扮饶,得知nativeWake被調(diào)用的條件為:

  1. next()方法在等待新消息具练,且新插入消息的為鏈表頭時。needWake為true
  2. 設(shè)置了Sync Barrier甜无,且插入的消息是“異步”的扛点。needWake為true

2.2 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);
    }
  • 在消息隊(duì)列的最前面插入一個消息,在消息循環(huán)的下一次迭代中進(jìn)行處理岂丘。
  • 由于它可以輕松的解決消息隊(duì)列的排序問題和其他的意外副作用陵究。

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

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

發(fā)送一個僅有what的Message
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);
    }
  • 發(fā)送一個僅有what的Message,并且延遲特定的時間發(fā)送
  • 這個方法內(nèi)部主要就是做了3件事

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

2.4 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);
    }
  • 發(fā)送一個僅有what的Message秸苗,并且在特定的時間發(fā)送
  • 這個方法內(nèi)部主要就是做了3件事
  • 1召娜、調(diào)用Message.obtain();從消息對象池中獲取一個空的Message。
  • 2惊楼、設(shè)置這個Message的what值
  • 3萤晴、調(diào)用sendMessageAtTime(Message,long) 將這個消息方法

2.5 小結(jié)

這些send方案都會從這里或者那里最終走到boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis)


5713484-e56c82c4e36768f5.png

3 Handler的post方案

3.1 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);
    }
  • 將一個Runnable添加到消息隊(duì)列中,這個runnable將會在和當(dāng)前Handler關(guān)聯(lián)的線程中被執(zhí)行胁后。

  • 就是調(diào)用了sendMessageDelayed(Message, long);這個方法店读,所以可見boolean post(Runnable r)這個方法最終還是走到上面說到的send的流程中

  • 最終調(diào)用boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis)。

3.1.1 Message getPostMessage(Runnable r)方法

代碼在Handler.java 725行

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

代碼很簡單攀芯,主要是做了兩件事

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

最后返回這個Message m屯断。

3.1.2 小結(jié)

  • boolean post(Runnable r)方法的內(nèi)置也是通過Message.obtain()來獲取一個Message對象m,然后僅僅把m的callback指向參數(shù)r而已侣诺。
  • 最后最終通過調(diào)用send方案的某個流程最終調(diào)用到boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis)

3.2 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);
    }
  • 將一個Runnable添加到消息隊(duì)列中殖演,這個runnable將會一個特定的時間被執(zhí)行,這個時間是以android.os.SystemClock.uptimeMillis()為基準(zhǔn)年鸳。
  • 如果在深度睡眠下趴久,會推遲執(zhí)行的時間,這個Runnable將會在和當(dāng)前Hander關(guān)聯(lián)的線程中被執(zhí)行搔确。
  • 方法內(nèi)部也是先是調(diào)用getPostMessage(Runnable)來獲取一個Message彼棍,這個Message的callback字段指向了這個Runnable,然后調(diào)用sendMessageAtTime(Message,long)膳算。

3.3 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);
    }
  • 這個方法和上個方法唯一不同就是多了Object參數(shù)座硕,而這個參數(shù)僅僅是把Message.obtain();獲取的Message的obj字段的指向第二個入?yún)oken而已。最后也是調(diào)用sendMessageAtTime(Message,long)涕蜂。

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

這個方法也很簡單华匾,就是依舊是通過getPostMessage(Runnable)來獲取一個Message,最后調(diào)用sendMessageDelayed(Message,long)而已机隙。

3.5 boolean postAtFrontOfQueue(Runnable r)方法

代碼在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));
    }

就是依舊是通過getPostMessage(Runnable)來獲取一個Message蜘拉,最后調(diào)用sendMessageAtFrontOfQueue(Message)而已。

3.6 小結(jié)

  • Handler的post方案:都是通過Message getPostMessage(Runnable )中調(diào)用Message m = Message.obtain();來獲取一個空的Message有鹿,然后把這個Message的callback變量指向了Runnable旭旭,最終調(diào)用相應(yīng)的send方案而已。

所以我們可以這樣說:
Handler的發(fā)送消息(障柵除外)印颤,無論是通過send方案還是pos方案最終都會做走到 boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) 中

5713484-5d5c06c67b925a3d.png

參考

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末您机,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌际看,老刑警劉巖咸产,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異仲闽,居然都是意外死亡脑溢,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進(jìn)店門赖欣,熙熙樓的掌柜王于貴愁眉苦臉地迎上來屑彻,“玉大人,你說我怎么就攤上這事顶吮∩缟” “怎么了?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵悴了,是天一觀的道長搏恤。 經(jīng)常有香客問我,道長湃交,這世上最難降的妖魔是什么熟空? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮搞莺,結(jié)果婚禮上息罗,老公的妹妹穿的比我還像新娘。我一直安慰自己才沧,他們只是感情好迈喉,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著糜工,像睡著了一般弊添。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上捌木,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天,我揣著相機(jī)與錄音嫉戚,去河邊找鬼刨裆。 笑死,一個胖子當(dāng)著我的面吹牛彬檀,可吹牛的內(nèi)容都是我干的帆啃。 我是一名探鬼主播,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼窍帝,長吁一口氣:“原來是場噩夢啊……” “哼努潘!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤疯坤,失蹤者是張志新(化名)和其女友劉穎报慕,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體压怠,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡眠冈,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了菌瘫。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蜗顽。...
    茶點(diǎn)故事閱讀 39,711評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖雨让,靈堂內(nèi)的尸體忽然破棺而出雇盖,到底是詐尸還是另有隱情,我是刑警寧澤栖忠,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布崔挖,位于F島的核電站,受9級特大地震影響娃闲,放射性物質(zhì)發(fā)生泄漏虚汛。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一皇帮、第九天 我趴在偏房一處隱蔽的房頂上張望卷哩。 院中可真熱鬧,春花似錦属拾、人聲如沸将谊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽尊浓。三九已至洽议,卻和暖如春瘤睹,著一層夾襖步出監(jiān)牢的瞬間帅戒,已是汗流浹背竹伸。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工洽洁, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留饲做,地道東北人逼纸。 一個月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓嗅蔬,卻偏偏與公主長得像歌亲,于是被迫代替她去往敵國和親菇用。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評論 2 353

推薦閱讀更多精彩內(nèi)容