Android Handler機(jī)制系列文章整體內(nèi)容如下:
- Android Handler機(jī)制1之Thread
- Android Handler機(jī)制2之ThreadLocal
- Android Handler機(jī)制3之SystemClock類
- Android Handler機(jī)制4之Looper與Handler簡(jiǎn)介
- Android Handler機(jī)制5之Message簡(jiǎn)介與消息對(duì)象對(duì)象池
- Android Handler機(jī)制6之MessageQueue簡(jiǎn)介
- Android Handler機(jī)制7之消息發(fā)送
- Android Handler機(jī)制8之消息的取出與消息的其他操作
- Android Handler機(jī)制9之Handler的Native實(shí)現(xiàn)前奏之Linux IO多路復(fù)用
- Android Handler機(jī)制10之Handdler的Native實(shí)現(xiàn)Native的實(shí)現(xiàn)
- Android Handler機(jī)制11之Handler機(jī)制總結(jié)
- Android Handler機(jī)制12之Callable、Future和FutureTask
- Android Handler機(jī)制13之AsyncTask源碼解析
本片文章的主要內(nèi)容如下:
- 1、Handler發(fā)送消息
- 2、Handler的send方案
- 3、Handler的post方案
一 、Handler發(fā)送消息
大家平時(shí)發(fā)送消息主要是調(diào)用的兩大類方法
如下兩圖:


光看上面這些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ì)


總結(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)如下圖

三、 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) 中
