序
Handler原理注意是消息处理机制。
- Message:消息的bean类,主要包含what,data, callback等信息;
- Handler:消息的搬运工,主要是发送和处理;
- MessageQueue:消息队列,主要是效果的管理;
- Looper:在ThreadLocal里面,用来启动MessageQueue,会调用MessageQueue的next方法。主线程默认启动了
for (;;) {
Message msg = queue.next(); // might block
消息队列启动。
通过Looper.loop()启动,主线程默认启动了,其他线程需要自己启动,否则不能进行消息处理。
ThreadLocal:构造方法是私有,通过获取当前的线程作为变量,保证每个线程的ThreadLocal只会是调用者的。
消息分发
如果是post还是postDelay,最终都会调用到:
public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
这是系统的开机时间,所以系统休眠了,会到延时处理失败。
消息队列排序:在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;
}
根据代码如果我们要实现一个高优先级的消息,只需要把当前时间设置会0,就会插入到堆首,以保证可以快速响应。
消息分发
根据Looper.loop()方法,会不断调用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);
内部也是一个死循环,会不断暂停在nativePollOnce方法中,nextPollTimeoutMillis是暂停时间,其中的是遍历所有消息队列得到的值。-1表示永久阻塞,直至有新消息进来,唤醒。
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会调用dispatchMessage方法
try {
msg.target.dispatchMessage(msg);
if (observer != null) {
observer.messageDispatched(token, msg);
}
dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
}
target:Message的handler,最终调用:
/**
* 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);
}
}
最后就会执行我们重写的handleMessage方法。
网友评论