模型
Message
:消息实体,携带着需要处理的各种任务信息Handler
:作为 Message 的 Target,用于创建、发布、处理 Message。MessageQueue
:消息队列,内部实现使用的是单链表,用于存取 Message。Looper
:消息循环,不断执行loop()
方法从 MessageQueue 取出 Message,按分发机制分发给 Handler
架构
Hanlder、Looper、MessageQueue的关系
参考Looper、Message、Handler和HandlerThread之间的关系
流程
由 Handler 发送一条消息之后(该 Handler 就成为消息的目标 Target),MessageQueue 调用enqueueMessage()
方法按时间向消息队列中插入消息。Looper 开启loop()
循环,调用MessageQueue.next()
读取消息,然后调用消息目标 Handler 的dispatchMessage()
方法传递消息,再切换回 Handler 的线程,调用Handler.handleMessage()
方法处理消息
源码解析
Looper
消息机制首先需要创建一个 Looper。包括了对 Looper 的初始化和开启循环。
初始化
/**
* Initialize the current thread as a looper.
* This gives you a chance to create handlers that then reference
* this looper, before actually starting the loop. Be sure to call
* {@link #loop()} after calling this method, and end it by calling
* {@link #quit()}.
*
* 为当前线程初始化 Looper,在此之后需要调用{@link #loop()}。
* 结束 Looper 时需要调用{@link #quit()}
*/
public static void prepare() {
prepare(true);
}
private static void prepare(boolean quitAllowed) {
// 不能重复初始化 Looper,否则会抛出异常。
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
// 构造出来的 Looper 会保存到线程本地存储区`ThreadLocal`中(简称TLS)。
// quitAllowed 决定了 Looper 关联创建的 MessageQueue 是否允许退出。
sThreadLocal.set(new Looper(quitAllowed));
}
开启循环
/**
* Run the message queue in this thread. Be sure to call
* {@link #quit()} to end the loop.
*/
public static void loop() {
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
final MessageQueue queue = me.mQueue;
···
for (;;) {
// 在这个死循环中调用 next() 拿下一条消息,没有的话会阻塞等待 MessageQueue 加入消息再重新唤醒
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
···
// 拿到消息之后会使用消息的目标 Handler 去分发消息
msg.target.dispatchMessage(msg);
···
}
}
在主线程中,系统已经帮我们初始化了 Looper:
public static void main(String[] args) {
···
// 内部调的是 Looper 的 prepare(false)
Looper.prepareMainLooper();
···
Looper.loop();
···
}
Handler
创建
Handler 有多个构造方法,但大部分为隐藏的
/**
* 使用当前线程的 Looper,如果当前线程没有 Looper 就不能接收信息,因此会抛出异常
*/
public Handler() {
this(null, false);
}
/**
* @hide
*/
public Handler(Callback callback, boolean async) {
···
// 当前线程的 Looper
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
// 当前 Looper 的 MessageQueue
mQueue = mLooper.mQueue;
// Handler 的回调
mCallback = callback;
// 是否为异步消息
mAsynchronous = async;
}
发送消息
Handler 有很多 post 和 send 方法,最终调用的都是sendMessageAtTime(msg, uptimeMillis)
:
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);
}
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
可以看到最终是调用了 对应 MessageQueue 的enqueueMessage(msg, uptimeMillis)
方法:
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) {
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;
if (p == null || when == 0 || when < p.when) {
// New head, wake up the event queue if blocked.
/*
* 如果拿到头部消息为空、或当前消息时间为 0、或当前消息的时间比头部消息的时间小,
* 那么把当前消息作为新的头部消息,并在 MessageQueue 阻塞的情况下唤醒
*/
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();
/*
* 这里利用 for 循环将当前消息按时间顺序插入到队列中
*/
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;
}
// We can assume mPtr != 0 because mQuitting is false.
if (needWake) {
nativeWake(mPtr);
}
}
return true;
}
获取消息
获取消息最主要的还是 MessageQueue 中的next()
方法
Message 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;
}
// 第一次迭代,pendingIdleHandlerCount 为 -1
int pendingIdleHandlerCount = -1; // -1 only during first iteration
int nextPollTimeoutMillis = 0;
for (;;) {
if (nextPollTimeoutMillis != 0) {
Binder.flushPendingCommands();
}
nativePollOnce(ptr, nextPollTimeoutMillis);
synchronized (this) {
// Try to retrieve the next message. Return if found.
final long now = SystemClock.uptimeMillis();
Message prevMsg = null;
Message msg = mMessages;
if (msg != null && msg.target == null) {
// Stalled by a barrier. Find the next asynchronous message in the queue.
// 当消息的目标 Handler 为空则寻找消息队列中的下一条异步消息
do {
prevMsg = msg;
msg = msg.next;
} while (msg != null && !msg.isAsynchronous());
}
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
nextPollTimeoutMillis = -1;
}
// If first time idle, then get the number of idlers to run.
// Idle handles only run if the queue is empty or if the first message
// in the queue (possibly a barrier) is due to be handled in the future.
/*
* 首次迭代并且消息为空或者当前时间比消息时间小,获取 IdleHandler 的个数。
* IdleHandler 用于阻塞等待消息时回调,只会在消息队列为空或者头部消息未到处理时间的时候运行。
*/
if (pendingIdleHandlerCount < 0
&& (mMessages == null || now < mMessages.when)) {
pendingIdleHandlerCount = mIdleHandlers.size();
}
if (pendingIdleHandlerCount <= 0) {
// No idle handlers to run. Loop and wait some more.
// 如果没有 IdleHandler 运行,则重新轮询等待消息
mBlocked = true;
continue;
}
if (mPendingIdleHandlers == null) {
mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
}
mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
}
// Run the idle handlers.
// We only ever reach this code block during the first iteration.
// 只有第一次迭代的时候会调用以下代码段
for (int i = 0; i < pendingIdleHandlerCount; i++) {
final IdleHandler idler = mPendingIdleHandlers[i];
mPendingIdleHandlers[i] = null; // release the reference to the handler
boolean keep = false;
try {
keep = idler.queueIdle();
} catch (Throwable t) {
Log.wtf(TAG, "IdleHandler threw exception", t);
}
if (!keep) {
synchronized (this) {
mIdleHandlers.remove(idler);
}
}
}
// Reset the idle handler count to 0 so we do not run them again.
// 重置 pendingIdleHandlerCount 为0,使得下次不再调用相关代码段
pendingIdleHandlerCount = 0;
// While calling an idle handler, a new message could have been delivered
// so go back and look again for a pending message without waiting.
// 调用 IdleHandler 时可能会有新的消息被分发,因此这里把延时设置为0,再轮询一次
nextPollTimeoutMillis = 0;
}
}
分发消息
分发消息的方法在 Handler 中:
public void dispatchMessage(Message msg) {
// 如果消息有自己的 Runnable,则执行 Runnable
if (msg.callback != null) {
handleCallback(msg);
} else {
// 如果 Handler 构造时传入了 Callback,则执行 Callback 方法
if (mCallback != null) {
// 如果返回 true,说明接下来不需要处理后续事件
if (mCallback.handleMessage(msg)) {
return;
}
}
// 正常处理消息
handleMessage(msg);
}
}
/**
* 空实现,由子类自己覆写,用于接收并处理消息
*/
public void handleMessage(Message msg) {
}
从方法可以看出,消息分发的优先级由大到小分别是:
- Message 本身的
callback
,内部实际上是个Runnable
,构造时传入 - Handler 本身的
mCallback
,属于 Handler 的内部接口,构造时传入 - 当第二点返回false,则调用正常处理消息的方法,该方法由 Handler 子类覆写实现