Handler主要作用一句話概括:線程間通信。
在日常開(kāi)發(fā)中主要作用于兩方面:</br>
????????1、在UI線程進(jìn)行耗時(shí)操作時(shí),將耗時(shí)操作拋到子線程進(jìn)行處理,否則容易ANR。</br>
????????2、在子線程中刷新UI。</br>
一、Handler簡(jiǎn)介
????????Handler、Looper、MessageQueue 和 Message 是組成Handler通信機(jī)制的基礎(chǔ)。</br>
1.1Handler簡(jiǎn)單使用
????????Handler的使用基本如以下代碼所示,或者繼承Handler重寫(xiě)handleMessage,處理不同what標(biāo)識(shí)的Message。不是本文討論的重點(diǎn),不做過(guò)多敘述。
//創(chuàng)建子線程Handler
HandlerThread mHandlerThread = new HandlerThread("daqi");
Handler mHandler = new Handler(mHandlerThread.getLooper());
//創(chuàng)建Message
Message message = mHandler.obtainMessage();
//發(fā)送Message
mHandler.sendMessage(message);
//post
mHandler.post(new Runnable() {
@Override
public void run() {
}
});
1.2Handler工作流程
????????創(chuàng)建Handler,并綁定Looper -> Handler發(fā)送Message -> Message存儲(chǔ)到Looper的MessageQueue中 -> Looper在MessageQueue中拿取頂部Message -> 將Message發(fā)送給目標(biāo)Handler
Handler、Looper、MessageQueue 和 Message的關(guān)系:</br>
- 一個(gè)線程只能有一個(gè)Looper;</br>
- 一個(gè)Handler只能綁定一個(gè)Looper;</br>
- 多個(gè)Handler可以綁定同一個(gè)Looper;</br>
- 一個(gè)Looper管理著一個(gè)MessageQueue。</br>
- MssageQueue作為Message“收信箱”,收納著Handler發(fā)送的Message。</br>
二、提出問(wèn)題
帶著問(wèn)題看源碼:</br>
????1、Looper如何確保線程中只有一個(gè)單例。</br>
????2、為什么建議使用Handler#obtainMessage()獲取Message對(duì)象,而不是直接new。</br>
????3、Handler的sendMessage() 和 post()有什么區(qū)別。</br>
????4、Looper如何管理Message隊(duì)列(即先后發(fā)送不同延遲時(shí)間的Message,Message隊(duì)列如何排序)。</br>
????5、removeCallbacks、removeMessages 和 removeCallbacksAndMessages都移除了什么。</br>
三、源碼分析
3.1、Looper機(jī)制
Handler在創(chuàng)建時(shí),默認(rèn)構(gòu)造方法會(huì)綁定當(dāng)前線程。所以我們選擇先從Handler的默認(rèn)構(gòu)造方法看起。
#Handler.java
//無(wú)參構(gòu)造函數(shù)
public Handler() {
this(null, false);
}
public Handler(Callback callback, boolean async) {
//....
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread " + Thread.currentThread()
+ " that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
}
????????創(chuàng)建Handler對(duì)象時(shí),無(wú)參構(gòu)造函數(shù)會(huì)獲取當(dāng)前線程的Looper并獲取到其MessageQueue存儲(chǔ)到Handler自身變量中。
????????但我們也觀察到,如果沒(méi)有Looper的Thread中創(chuàng)建,會(huì)拋出RuntimeException,并告訴你該線程無(wú)Looper。
????????從Handler的默認(rèn)構(gòu)造方法中得知,在創(chuàng)建Handler前,需要先在當(dāng)前線程中創(chuàng)建Looper對(duì)象和MessageQueue對(duì)象。而創(chuàng)建Looper對(duì)象和MessageQueue對(duì)象只需要調(diào)用如下方法:
Looper.prepare();
Looper.loop();
????????prepare的意思是準(zhǔn)備,即可以猜測(cè)Looper是在Looper#prepare()中初始化的,所以先從Looper#prepare()的源碼看起:
#Looper.java
//主要用于作為存儲(chǔ)的Looper實(shí)例的key。
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
public static void prepare() {
prepare(true);
}
private static void prepare(boolean quitAllowed) {
//ThreadLocal#get()獲取當(dāng)前線程的looper對(duì)象
if (sThreadLocal.get() != null) {
//如果Looper已經(jīng)實(shí)例化完,則會(huì)拋出異常
throw new RuntimeException("Only one Looper may be created per thread");
}
//如果之前當(dāng)前線程沒(méi)有初始化過(guò)Looper,則創(chuàng)建Looper并添加到sThreadLocal中
sThreadLocal.set(new Looper(quitAllowed));
}
????????我們發(fā)現(xiàn)Looper#prepare()調(diào)用重載函數(shù)Looper#prepare(boolean)。在這方法中,Looper會(huì)被初始化。查看Looper私有構(gòu)造函數(shù),發(fā)現(xiàn)Looper會(huì)初始化MessageQueue并存儲(chǔ)當(dāng)前線程。
????????而Looper被初始化是有一個(gè)前提的,即sThreadLocal.get() == null。否則會(huì)拋出RuntimeException,并告訴你該線程只能創(chuàng)建一個(gè)Looper對(duì)象。
????????sThreadLocal是Looper類中定義的一個(gè)靜態(tài)ThreadLocal常量。繼續(xù)查看ThreadLocal#get()和ThreadLocal#set()方法。
#ThreadLocal.java
public T get() {
//獲取當(dāng)前線程
Thread t = Thread.currentThread();
//線程中存在一個(gè)ThreadLocal.ThreadLocalMap類型的變量
//根據(jù)當(dāng)前線程thread獲取到對(duì)應(yīng)的ThreadLocal.ThreadLocalMap變量。
ThreadLocalMap map = getMap(t);
if (map != null) {
//this表示Looper類中的靜態(tài)ThreadLocal常量sThreadLocal
//因?yàn)閟ThreadLocal是靜態(tài)常量,作為“key”,確保變量為單例。
//根據(jù)sThreadLocal獲取到對(duì)應(yīng)的ThreadLocalMap.Entry值。
ThreadLocalMap.Entry e = mapgetEntry(this);
if (e != null) {
//從ThreadLocalMap.Entry中獲取到對(duì)應(yīng)的Looper,
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}
public void set(T value) {
//獲取當(dāng)前線程
Thread t = Thread.currentThread();
//線程中存在一個(gè)ThreadLocal.ThreadLocalMap類型的變量
//根據(jù)當(dāng)前線程thread獲取到對(duì)應(yīng)的ThreadLocal.ThreadLocalMap變量。
ThreadLocalMap map = getMap(t);
if (map != null)
//將sThreadLocal作為“key”,Looper實(shí)例作為“value”存儲(chǔ)到ThreadLocal.ThreadLocalMap中
map.set(this, value);
else
//創(chuàng)建Map并存儲(chǔ)值
createMap(t, value);
}
void createMap(Thread t, T firstValue) {
//創(chuàng)建ThreadLocalMap,構(gòu)造方法中傳入第一次存儲(chǔ)的鍵值對(duì),并賦值到當(dāng)前線程的threadLocals變量中。
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
????????可以觀察到,get()和set()方法獲取當(dāng)前線程中的ThreadLocal.ThreadLocalMap變量。再將Looper#sThreadLocal作為key,存儲(chǔ)或獲取對(duì)應(yīng)的value,而value就是當(dāng)前線程創(chuàng)建的Looper實(shí)例。
????????get()時(shí)是根據(jù)當(dāng)前線程獲取的Looper單例,再結(jié)合Looper#prepare(boolean),可以知道單個(gè)線程只會(huì)生成Looper單個(gè)實(shí)例。
問(wèn)題1:Looper如何確保線程中只有一個(gè)單例。
????????回答:將Looper構(gòu)造方法私有化。通過(guò)Looper的靜態(tài)方法,確保只創(chuàng)建一次Looper對(duì)象,再將靜態(tài)常量sThreadLocal作為key,Looper對(duì)象作為value,存儲(chǔ)到當(dāng)前線程的ThreadLocal.ThreadLocalMap變量中。
查看完Looper初始化的流程,再看看Looper#loop()的源碼
#Looper.java
public static void loop() {
//獲取當(dāng)前線程的Looper
final Looper me = myLooper();
//如果Looper沒(méi)有初始化,則拋異常
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
//從Looper實(shí)例中獲取當(dāng)前線程的MessageQueue
final MessageQueue queue = me.mQueue;
//消息循環(huán)(通過(guò)for循環(huán))
for (;;) {
//1、從消息隊(duì)列中獲取消息
Message msg = queue.next();
if (msg == null) {
//沒(méi)有消息表明消息隊(duì)列正在退出。
return;
}
//省略代碼.....
//2、將Message發(fā)送給其標(biāo)記的targetHandler
msg.target.dispatchMessage(msg);
//省略代碼.....
//3、回收可繼續(xù)使用的Message
msg.recycleUnchecked();
}
}
Looper#loop()主要做3件事:
????1、不斷從MessageQueue中取出Message,若暫無(wú)Message,則無(wú)限等待。</br>
????2、將Message發(fā)送給目標(biāo)Handler進(jìn)行處理。</br>
????3、回收Message對(duì)象。</br>
????????但發(fā)現(xiàn)有一種情況,當(dāng)next獲取到的Message為空時(shí),則會(huì)退出Looper#loop()方法,即意味著消息循環(huán)結(jié)束。那什么時(shí)候MessageQueue#next()返回null?
#MessageQueue.java
Message next() {
//如果消息循環(huán)已經(jīng)退出并處理掉,請(qǐng)返回此處。
//如果應(yīng)用程序嘗試在退出后重新啟動(dòng)looper,則可能會(huì)發(fā)生這種情況。
//即MessageQueue調(diào)用了quit()方法,再次調(diào)用Looper#looper()方法時(shí)。
final long ptr = mPtr;
if (ptr == 0) {
return null;
}
//決定消息隊(duì)列中消息出隊(duì)的等待時(shí)間 or 標(biāo)記為無(wú)限等待狀態(tài)
int nextPollTimeoutMillis = 0;
for (;;) {
//.....
// nativePollOnce方法在native層方法。
//若是nextPollTimeoutMillis為-1,則無(wú)限等待,此時(shí)消息隊(duì)列處于等待狀態(tài)。
//若是nextPollTimeoutMillis為0,則無(wú)需等待立即返回。
//若nextPollTimeoutMillis>0,最長(zhǎng)阻塞nextPollTimeoutMillis毫秒(超時(shí)),如果期間有程序喚醒會(huì)立即返回。
nativePollOnce(ptr, nextPollTimeoutMillis);
//嘗試檢索下一條消息。 如果找到則返回。
synchronized (this) {
//獲取從開(kāi)機(jī)到現(xiàn)在的毫秒數(shù)
final long now = SystemClock.uptimeMillis();
Message prevMsg = null;
//獲取MessageQueue中的頂層Message
Message msg = mMessages;
//.....
if (msg != null) {
//如果massage的時(shí)間大于當(dāng)前時(shí)間
//Message的when = Handler發(fā)送Message1時(shí)的開(kāi)機(jī)時(shí)間SystemClock.uptimeMillis() + Message自身的延遲時(shí)間
if (now < msg.when) {
// 下一條消息尚未就緒。 設(shè)置該Message的等待時(shí)間以在準(zhǔn)備就緒時(shí)喚醒。
//將msg.when - now(當(dāng)前開(kāi)機(jī)時(shí)間) 得到該Message需要多久之后發(fā)送。
//則刷新nextPollTimeoutMillis的值,設(shè)置等待時(shí)間。
nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
} else {//否則馬上發(fā)送Message
//只有當(dāng)msg.target == null時(shí),prevMsg才會(huì)賦值。
//遵從Handler#obtainMessage()則一般不為空,此情況不考慮。
if (prevMsg != null) {
prevMsg.next = msg.next;
} else {
//剛開(kāi)始時(shí)prevMsg為空
//則mMessages(頂層Message)指向當(dāng)前頂層Message的下一個(gè)Message
mMessages = msg.next;
}
//將返回的Message的下一個(gè)Message引用置空。
msg.next = null;
msg.markInUse();
return msg;
}
} else {
//如果MessageQueue中沒(méi)有Message,則會(huì)將nextPollTimeoutMillis重置為-1,繼續(xù)等待
nextPollTimeoutMillis = -1;
}
//.....
}
//.....
}
}
????????從源碼開(kāi)頭得知,當(dāng)MessageQueue退出時(shí),MessageQueue#next()則會(huì)返回Message對(duì)象為空,從而關(guān)閉消息循環(huán)。
????MessageQueue#next()主要進(jìn)行等待操作和返回Message操作。而等待操作分兩種情況:
????????1、MessageQueue隊(duì)列中無(wú)Message,則進(jìn)行無(wú)限等待操作。
????????2、當(dāng)Message還沒(méi)到處理時(shí)間時(shí),則計(jì)算該Message還需要等待的時(shí)間,進(jìn)行相應(yīng)時(shí)間的延遲。
查看Handler如何處理Message:
#Handler.java
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
//如果Message的callback不為空,則將消息交由Message的callback處理
handleCallback(msg);
} else {
if (mCallback != null) {
//如果Handler的callback不為空,則將消息交由Handler的callback處理
if (mCallback.handleMessage(msg)) {
return;
}
}
//最后才交由Handler的handleMessage()方法處理。
handleMessage(msg);
}
}
????????Handler#dispatchMessage()主要作用時(shí)將Message分發(fā)處理。
????????當(dāng)該Message對(duì)象的callback為空,目標(biāo)Handler的callback也為空時(shí),才輪到handleMessage()進(jìn)行消息處理。
3.2、Message的循環(huán)再用機(jī)制
創(chuàng)建Message對(duì)象時(shí),我們一般會(huì)調(diào)用Handler#obtainMessage()獲取Message對(duì)象,而不是直接new。先從Handler#obtainMessage()開(kāi)始查看原由:
#Handler.java
public final Message obtainMessage(){
return Message.obtain(this);
}
#Message.java
//Message鏈表,sPool是表頭
private static Message sPool;
//記錄當(dāng)前鏈表中的數(shù)量
private static int sPoolSize = 0;
public static Message obtain(Handler h) {
Message m = obtain();
m.target = h;
return m;
}
public static Message obtain() {
//加鎖
synchronized (sPoolSync) {
if (sPool != null) {
Message m = sPool;
//鏈表表頭指向其下一個(gè)對(duì)象,即將表頭從鏈表中取出
sPool = m.next;
//重置返回的Message的一些信息
m.next = null;
m.flags = 0; // clear in-use flag
//鏈表數(shù)量減一
sPoolSize--;
return m;
}
}
//如果鏈表表頭為空,則new Message對(duì)象。
return new Message();
}
????????Message#obtain(Handler)調(diào)用了重載方法Message#obtain()獲取到Message對(duì)象并將Message的目標(biāo)設(shè)置為調(diào)用Handler#obtainMessage()的Message。
????????Message對(duì)象中擁有一個(gè)Message類型的next對(duì)象,可通過(guò)next屬性連成一個(gè)Message鏈表。Message中維系著一個(gè)靜態(tài)Message鏈表,當(dāng)鏈表不為空時(shí),取出表頭的Message進(jìn)行返回,否則new一個(gè)Message對(duì)象。
之前查看Looper#loop()源碼時(shí)獲知,Looper#loop()最后會(huì)調(diào)用Message#recycleUnchecked(),將Message進(jìn)行回收。
#Message.java
//Message鏈表最大存儲(chǔ)數(shù)量值
private static final int MAX_POOL_SIZE = 50;
void recycleUnchecked() {
//將消息保留在循環(huán)對(duì)象池中時(shí)將其標(biāo)記為正在使用。
//清除所有其他細(xì)節(jié)。
flags = FLAG_IN_USE;
what = 0;
arg1 = 0;
arg2 = 0;
obj = null;
replyTo = null;
sendingUid = -1;
when = 0;
target = null;
callback = null;
data = null;
//加鎖
synchronized (sPoolSync) {
//當(dāng)前鏈表存儲(chǔ)數(shù)量小于最大值,則繼續(xù)回收
if (sPoolSize < MAX_POOL_SIZE) {
//next代表的是該需要回收的Message自身的next對(duì)象
//將自身的next指向原表頭,
next = sPool;
//自身替換為表頭,則通過(guò)表頭的加減實(shí)現(xiàn)該Message鏈表的增加和刪除。
sPool = this;
//鏈表存儲(chǔ)數(shù)量加一
sPoolSize++;
}
}
}
????????Message#recycleUnchecked()將Message的參數(shù)重置,并判斷當(dāng)前Messag鏈表存儲(chǔ)的數(shù)量是否小于最大存儲(chǔ)值,若小于最大存儲(chǔ)值,則將該Message存儲(chǔ)到鏈表中,重復(fù)使用。</br>
????????Message通過(guò)對(duì)鏈表表頭的增刪操作來(lái)進(jìn)行鏈表的增減。
問(wèn)題2:為什么建議使用Handler#obtainMessage()獲取Message對(duì)象,而不是直接new。
????????回答:Message的回收機(jī)制其實(shí)是享元設(shè)計(jì)模式的實(shí)現(xiàn),Message對(duì)象存在需要反復(fù)、較大規(guī)模創(chuàng)建的情況,使用享元設(shè)計(jì)模式可以減少創(chuàng)建對(duì)象的數(shù)量,以減少內(nèi)存占用和提高性能。
總結(jié):
Message對(duì)象中擁有一個(gè)Message類型的next對(duì)象,可通過(guò)next屬性連成一個(gè)Message鏈表。
Message類中維系著個(gè)靜態(tài)Message鏈表,并標(biāo)記其存儲(chǔ)的數(shù)量值。
調(diào)用Handler#obtainMessage()或Message#obtain()方法時(shí),嘗試從該靜態(tài)鏈表中獲取循環(huán)再用的Message對(duì)象,否則new Message對(duì)象返回出去。
當(dāng)Message被Handler處理完后,Looper對(duì)象會(huì)調(diào)用Message#recycleUnchecked()將Message進(jìn)行回收,并存儲(chǔ)到靜態(tài)Message鏈表中。
3.3、Handler兩條發(fā)送路徑:sendMessage 和 post
我們都知道,Handler可以通過(guò)sendMessage和post進(jìn)行消息的發(fā)送,這兩種方法到底有什么區(qū)別?先從sendMessage看起:
#Handler.java
public final boolean sendMessage(Message msg){
//發(fā)送一個(gè)0延遲的message
return sendMessageDelayed(msg, 0);
}
public final boolean sendMessageDelayed(Message msg, long delayMillis){
//延遲值不能小于0
if (delayMillis < 0) {
delayMillis = 0;
}
//將延遲的時(shí)間和開(kāi)機(jī)時(shí)間相加
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
//獲取Handler創(chuàng)建時(shí)存儲(chǔ)的當(dāng)前線程的MessageQueue
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);
}
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
//將Message的目標(biāo)TargetHandler設(shè)置為當(dāng)前Handler
//如果通過(guò)Handler#obtainMessage()獲取的Message早設(shè)置了TargetHandler為當(dāng)前Handler,一般是新new的Message才為空。
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
????????一路都是方法的嵌套,其中最關(guān)鍵的就是在傳遞給sendMessageAtTime()方法前,將延時(shí)時(shí)間和手機(jī)開(kāi)機(jī)時(shí)間相加,得到Message對(duì)象的"執(zhí)行時(shí)間"。
在繼續(xù)查看MessageQueue#enqueueMessage():
#MessageQueue.java
//標(biāo)記MessageQueue#next()的nativePollOnce()是否以 非零超時(shí)等待(無(wú)限等待)被阻止。
private boolean mBlocked;
boolean enqueueMessage(Message msg, long when) {
//.....
synchronized (this) {
//...
msg.markInUse();
//將延遲時(shí)間和開(kāi)機(jī)時(shí)間相加得到的時(shí)間值存儲(chǔ)到message的when變量中。
msg.when = when;
//獲取鏈表表頭的Message
Message p = mMessages;
boolean needWake;
//當(dāng)表頭為空時(shí),或者本次發(fā)送的Message對(duì)象“執(zhí)行時(shí)間”比表頭的時(shí)間要小時(shí)
if (p == null || when == 0 || when < p.when) {
//將本次發(fā)送的Message存儲(chǔ)到表頭前面,將next屬性指向原鏈表表頭
msg.next = p;
//刷新MessageQueue中指向表頭的變量
mMessages = msg;
needWake = mBlocked;
} else {
//通常不需要喚醒事件隊(duì)列,除非隊(duì)列的頭部有屏障,并且消息是隊(duì)列中最早的異步消息。
needWake = mBlocked && p.target == null && msg.isAsynchronous();
Message prev;
//開(kāi)啟循環(huán),便利MessageQueue的Message鏈表
for (;;) {
//prev先指向原表頭,后續(xù)循環(huán)中,不斷指向下一個(gè)元素
prev = p;
//p指向下一個(gè)元素
p = p.next;
//如果p== null,表示到鏈表的尾部
//或者本次發(fā)送的Message對(duì)象的“執(zhí)行時(shí)間”when比下一個(gè)元素的“執(zhí)行時(shí)間”要短
if (p == null || when < p.when) {
//推出循環(huán)
break;
}
//...
}
//此時(shí),prev指向的Message對(duì)象的when 比本次發(fā)送的Message對(duì)象msg的when小,即“執(zhí)行時(shí)間”比它小。
//p可能為空,即鏈表尾;或者p指向的Message對(duì)象的when比 比本次發(fā)送的Message對(duì)象msg的when大,即“執(zhí)行時(shí)間”比它大。
// 即可能存在 prev.when < msg.when <p.when 或 prev.when < msg.when
//將msg的next變量指向p所指的對(duì)象
msg.next = p;
//prev所指向的message對(duì)象的next變量指向msg
prev.next = msg;
}
//判斷是否需要喚醒之前在MessageQueue#next()中“陷入沉睡”的nativePollOnce()方法。
if (needWake) {
nativeWake(mPtr);
}
}
return true;
}
MessageQueue#enqueueMessage()主要作用是:</br>
????????1、依據(jù)msg.when的大小,按從小到大的順序,將msg插入到MessageQueue的Message鏈表中。</br>
????????2、對(duì)于馬上執(zhí)行的message,直接喚醒,停止nativePollOnce()的無(wú)限等待,讓MessageQueue#next返回繼續(xù)執(zhí)行,從Message鏈表中取出Message,交由Looper對(duì)象進(jìn)行處理。</br>
模擬情況:</br>
????同時(shí)發(fā)送延遲400毫秒的Message對(duì)象 和 延遲300毫秒的Message對(duì)象;</br>
????100毫秒后,再發(fā)送延遲延遲250毫秒的Message對(duì)象;
情景分析:</br>
????????同時(shí)發(fā)送兩個(gè)分別延遲400和延遲300的Message對(duì)象,此時(shí)系統(tǒng)開(kāi)機(jī)時(shí)間 time = SystemClock.uptimeMillis();
????延遲400的Message對(duì)象:msg400, msg400 .when = time + 400;。</br>
首先進(jìn)入MessageQueue的Message鏈表,由于原本Message鏈表為空,p == null,表頭mMessages指 msg400
????延遲300的Message對(duì)象:msg300, msg300.when = time + 300;。</br>
進(jìn)入if(p == null || when == 0 || when < p.when)語(yǔ)句 ,p != null ,msg300.when < msg400.when , msg300.next 指向 msg400,鏈表表頭指向msg300;
????100毫秒后,發(fā)送延遲延遲250毫秒的Message對(duì)象。此時(shí)系統(tǒng)開(kāi)機(jī)時(shí)間 time2 = SystemClock.uptimeMillis(),相對(duì)time 大了100毫秒,即time2 = time + 100毫秒。
????延遲250的Message對(duì)象:msg250, msg250.when = time2 + 250, 即msg250.when = time + 350。</br>
????進(jìn)入if(p == null || when == 0 || when < p.when)語(yǔ)句,語(yǔ)句不成立,進(jìn)入遍歷Message鏈表的for循環(huán)。when < p.when判斷中,msg250.when > msg300.when,循環(huán)繼續(xù)。msg250.when < msg400.when,跳出循環(huán)。執(zhí)行msg.next = p; 和 prev.next = msg;兩個(gè)語(yǔ)句,即msg250.next = msg400,msg300.next = msg250。

問(wèn)題4:Looper如何管理Message隊(duì)列(即先后發(fā)送不同延遲時(shí)間的Message,Message隊(duì)列如何排序)。
????????回答:Message通過(guò)SystemClock.uptimeMillis() + 延遲時(shí)間給自身when賦值,通過(guò)值的大小作為執(zhí)行順序。SystemClock.uptimeMillis() 不根據(jù)當(dāng)前時(shí)區(qū)的時(shí)間變化而變化,只會(huì)因開(kāi)關(guān)機(jī)而被重置,否則始終自增。</br>
????????所以可以根據(jù)當(dāng)前的SystemClock.uptimeMillis() 與Message對(duì)象的when對(duì)比,知道馬上執(zhí)行還是延遲多少秒后才執(zhí)行。
轉(zhuǎn)換到Handler#ost()的源碼:
#Handler.java
public final boolean post(Runnable r){
return sendMessageDelayed(getPostMessage(r), 0);
}
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
//如果Message的callback不為空,則將消息交由Message的callback處理
handleCallback(msg);
} else {
if (mCallback != null) {
//如果Handler的callback不為空,則將消息交由Handler的callback處理
if (mCallback.handleMessage(msg)) {
return;
}
}
//最后才交由Handler的handleMessage()方法處理。
handleMessage(msg);
}
}
private static void handleCallback(Message message) {
//只是調(diào)用callback的run()方法。
message.callback.run();
}
????????post()傳遞的Runnable對(duì)象會(huì)被套上一層Message外殼,最后走和sendMessage()一樣的路線。
????????Runnable對(duì)象將存儲(chǔ)在Message對(duì)象的callback對(duì)象中。在Handler處理Message時(shí),由于callback對(duì)象不為空,調(diào)用Handler#handleCallback()對(duì)Runnable對(duì)象調(diào)用run()方法,實(shí)現(xiàn)Message的處理。
問(wèn)題3:Handler的sendMessage() 和 post()有什么區(qū)別。
????????回答:post()會(huì)將Runnable對(duì)象轉(zhuǎn)換為Message對(duì)象,并把Runnable對(duì)象存儲(chǔ)在Message對(duì)象的callback中,然后繼續(xù)走sendMessage()的路線。</br>
????????在Handler處理Message對(duì)象時(shí),post()方法產(chǎn)生的Message對(duì)象中callback不為空,由Handler調(diào)用Runnable對(duì)象的run方法,不會(huì)調(diào)用handleMessage();
3.4、Message的移除
#Handler.java
public final void removeMessages(int what) {
mQueue.removeMessages(this, what, null);
}
public final void removeCallbacks(Runnable r){
mQueue.removeMessages(this, r, null);
}
public final void removeMessages(int what, Object object) {
mQueue.removeMessages(this, what, object);
}
public final void removeCallbacks(Runnable r, Object token){
mQueue.removeMessages(this, r, token);
}
#MessageQueue.java
void removeMessages(Handler h, int what, Object object) {
//...
synchronized (this) {
//獲取Message鏈表表頭
Message p = mMessages;
//從頭開(kāi)始尋找,尋找第一個(gè)不符合條件的Message。分兩種情況:
//1、鏈表表頭直接不符合移除條件,即第一個(gè)不符合條件的Message為鏈表表頭,推出循環(huán)。
//2、鏈表符合移除條件,將鏈表表頭指向原表頭的下一個(gè)Message,并回收原鏈表表頭。新的鏈表表頭繼續(xù)進(jìn)行判斷,直到出現(xiàn)不符合移除條件的Message出現(xiàn)。
//最后鏈表表頭mMessages 和 p都指向第一個(gè)不符合條件的Message,前面符合移除條件的Message已被移除。
while (p != null && p.target == h && p.what == what
&& (object == null || p.obj == object)) {
Message n = p.next;
mMessages = n;
p.recycleUnchecked();
p = n;
}
//從第一個(gè)不符合條件的Message對(duì)象開(kāi)始,迭代尋找其下一個(gè)Message是否符合移除條件。
while (p != null) {
Message n = p.next;
if (n != null) {
//判斷是否符合移除條件
if (n.target == h && n.what == what
&& (object == null || n.obj == object)) {
//獲取p.next().next()的Message對(duì)象,即下下個(gè)對(duì)象。
Message nn = n.next;
//符合條件的回收
n.recycleUnchecked();
//將原本的下下個(gè)Message轉(zhuǎn)移到next對(duì)象中,即轉(zhuǎn)移到下一個(gè)Message的位置上。
p.next = nn;
continue;
}
}
//n == null,表示到鏈尾了,則 p == null,while循環(huán)結(jié)束。
p = n;
}
}
}
void removeMessages(Handler h, Runnable r, Object object) {
if (h == null || r == null) {
return;
}
synchronized (this) {
Message p = mMessages;
// Remove all messages at front.
while (p != null && p.target == h && p.callback == r
&& (object == null || p.obj == object)) {
Message n = p.next;
mMessages = n;
p.recycleUnchecked();
p = n;
}
// Remove all messages after front.
while (p != null) {
Message n = p.next;
if (n != null) {
if (n.target == h && n.callback == r
&& (object == null || n.obj == object)) {
Message nn = n.next;
n.recycleUnchecked();
p.next = nn;
continue;
}
}
p = n;
}
}
}
????????removeMessages(Handler, int, Object) 根據(jù)Message中的what進(jìn)行刷選移除對(duì)象。</br>
????????removeMessages(Handler, Runnable,Object)則根據(jù)相同的Runnable對(duì)象進(jìn)行刷選移除。
????????兩者的都是走相同的移除對(duì)象流程,只是其中的一種刷選條件有所不同,what針對(duì)的是Handler#sendMessage()發(fā)送的Message,Runnable針對(duì)的是Handler#post()發(fā)送的Message。
????????Handler#removeCallbacksAndMessages()則移除這兩種刷選條件,針對(duì)所有Message。
問(wèn)題5:removeCallbacks、removeMessages 和 removeCallbacksAndMessages都移除了什么
????????回答:removeCallbacks、removeMessages 和 removeCallbacksAndMessages 在待處理的Message鏈表中,根據(jù)各自的刷選條件尋找符合移除條件的對(duì)象,將符合條件的Message移除出Message鏈表,并回收該Message。
四、總結(jié)
- Message對(duì)象中擁有一個(gè)Message類型的next對(duì)象,可通過(guò)next屬性連成一個(gè)Message鏈表。
- Message類中維系著個(gè)靜態(tài)Message鏈表,存儲(chǔ)著回收的Message對(duì)象,等待重復(fù)使用。
- MessageQueue類中也維系著個(gè)靜態(tài)Message鏈表,存儲(chǔ)著待處理的Message的對(duì)象,等待MessageQueue#next()方法將其取出,交由目標(biāo)Handler處理。
- 當(dāng)用戶調(diào)用Handler#obtainMessage()時(shí),嘗試從該Message鏈表中獲取待循環(huán)再用的Message,獲取失敗則new一個(gè)新的Message對(duì)象。</br>
當(dāng)Message被目標(biāo)Handler處理完成后,會(huì)被回收到Message類的靜態(tài)Message鏈表中。</br>
當(dāng)調(diào)用Handler一系列remove方法后,被移除的Message會(huì)被回收到Message類的靜態(tài)Message鏈表中。 - post方法發(fā)送的Runnable對(duì)象將會(huì)被包裝成一個(gè)Message走sendMessage路線,Runnable對(duì)象被存儲(chǔ)在Message的callback變量中。
- 當(dāng)該Message對(duì)象的callback為空,目標(biāo)Handler的callback也為空時(shí),才將Message交由handleMessage()進(jìn)行處理。即post方法產(chǎn)生的Message對(duì)象會(huì)被交由Handler#handleCallback()直接調(diào)用run方法,不走Handler#handleMessage()。
- msg.when = 延時(shí)時(shí)間 + 手機(jī)開(kāi)機(jī)時(shí)間。再依據(jù)msg.when的大小,按從小到大的順序,將msg插入到MessageQueue的Message鏈表中。
- Looper類中的靜態(tài)ThreadLocal常量作為key,當(dāng)前線程的Looper對(duì)象做為value,存儲(chǔ)在當(dāng)前線程的ThreadLocal.ThreadLocalMap變量。ThreadLocal常量確保key唯一,也就確保value唯一,并且Looper#prepare()只允許創(chuàng)建一遍L(zhǎng)ooper對(duì)象。