序
Handler原理注意是消息處理機(jī)制。
- Message:消息的bean類,主要包含what,data, callback等信息;
- Handler:消息的搬運工,主要是發(fā)送和處理;
- MessageQueue:消息隊列,主要是效果的管理;
- Looper:在ThreadLocal里面,用來啟動MessageQueue,會調(diào)用MessageQueue的next方法。主線程默認(rèn)啟動了
for (;;) {
Message msg = queue.next(); // might block
消息隊列啟動。
通過Looper.loop()啟動,主線程默認(rèn)啟動了,其他線程需要自己啟動,否則不能進(jìn)行消息處理。
ThreadLocal:構(gòu)造方法是私有,通過獲取當(dāng)前的線程作為變量,保證每個線程的ThreadLocal只會是調(diào)用者的。
消息分發(fā)
如果是post還是postDelay,最終都會調(diào)用到:
public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
這是系統(tǒng)的開機(jī)時間,所以系統(tǒng)休眠了,會到延時處理失敗。
消息隊列排序:在MessageQueue.enqueueMessage插入的時候排序
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 {
// 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.
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;
}
根據(jù)代碼如果我們要實現(xiàn)一個高優(yōu)先級的消息,只需要把當(dāng)前時間設(shè)置會0,就會插入到堆首,以保證可以快速響應(yīng)。
消息分發(fā)
根據(jù)Looper.loop()方法,會不斷調(diào)用next方法。
// Return here if the message loop has already quit and been disposed.
// This can happen if the application tries to restart a looper after quit
// which is not supported.
final long ptr = mPtr;
if (ptr == 0) {
return null;
}
int pendingIdleHandlerCount = -1; // -1 only during first iteration
int nextPollTimeoutMillis = 0;
for (;;) {
if (nextPollTimeoutMillis != 0) {
Binder.flushPendingCommands();
}
nativePollOnce(ptr, nextPollTimeoutMillis);
內(nèi)部也是一個死循環(huán),會不斷暫停在nativePollOnce方法中,nextPollTimeoutMillis是暫停時間,其中的是遍歷所有消息隊列得到的值。-1表示永久阻塞,直至有新消息進(jìn)來,喚醒。
next方法會返回下一個需要處理的消息。
if (msg != null) {
if (now < msg.when) {
// Next message is not ready. Set a timeout to wake up when it is ready.
nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
} else {
// Got a message.
mBlocked = false;
if (prevMsg != null) {
prevMsg.next = msg.next;
} else {
mMessages = msg.next;
}
msg.next = null;
if (DEBUG) Log.v(TAG, "Returning message: " + msg);
msg.markInUse();
return msg;
}
} else {
// No more messages.
nextPollTimeoutMillis = -1;
}
獲取到待處理Message,Looper會調(diào)用dispatchMessage方法
try {
msg.target.dispatchMessage(msg);
if (observer != null) {
observer.messageDispatched(token, msg);
}
dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
}
target:Message的handler,最終調(diào)用:
/**
* Handle system messages here.
*/
public void dispatchMessage(@NonNull Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
最后就會執(zhí)行我們重寫的handleMessage方法。