1. 线程绑定机制
Looper 与 Handler 的绑定:
Looper.myLooper()
获取当前线程的 Looper,绑定其 MessageQueue
。Looper.prepare(); // 主动创建 Looper
Handler handler = new Handler(Looper.myLooper()); // 绑定当前线程 Looper
Handler 最终构造函数:public Handler(@NonNull Looper looper, @Nullable Callback callback, boolean async,
boolean shared) {
mLooper = looper;
mQueue = looper.mQueue; // 绑定 MessageQueue
mCallback = callback;
mAsynchronous = async;
mIsShared = shared;
}
Looper
prepare()
时会将自己放入 ThreadLocal
中:@UnsupportedAppUsage
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<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()}.
*/
public static void prepare() {
prepare(true);
}
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
// 获取当前线程 Looper
/**
* Return the Looper object associated with the current thread. Returns
* null if the calling thread is not associated with a Looper.
*/
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
// 获取 Looper 对应的 MessageQueue
/**
* Return the {@link MessageQueue} object associated with the current
* thread. This must be called from a thread running a Looper, or a
* NullPointerException will be thrown.
*/
public static @NonNull MessageQueue myQueue() {
return myLooper().mQueue;
}
// 私有构造函数,MainLooper 不允许退出,所以 quitAllowed 会是 False,其它 Looper 按需
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
发送消息:
无论调用哪个发送消息,最后都会走到 enqueueMessage
方法,该方法会使用 mQueue 的 enqueueMessage
方法
private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,
long uptimeMillis) {
msg.target = this;
msg.workSourceUid = ThreadLocalWorkSource.getUid();
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
2. 消息传递流程
步骤 | 操作 | 说明 |
---|---|---|
① | handler.sendMessage(msg) |
将消息加入绑定线程的 MessageQueue |
② | Looper.loop() |
循环从队列取出消息 |
③ | Handler.dispatchMessage() |
执行消息回调或 Runnable.run() |
3. 跨线程特性
sendMessage()
,消息始终由目标线程的 MessageQueue
处理。1. 核心作用
2. 工作机制
屏障插入
MessageQueue.postSyncBarrier()
插入屏障节点(handler == null
)。Looper.next()
遍历到屏障节点时开始生效。消息过滤规则
消息类型 | isAsynchronous == false |
isAsynchronous == true |
---|---|---|
同步消息 | 被屏障拦截(暂缓执行) | 允许通过 |
异步消息 | 强制通过 | 允许通过 |
MessageQueue.removeSyncBarrier(token)
恢复同步消息执行。1. 消息状态流转
待处理 → [被屏障拦截] → [屏障移除后继续执行]
2. 数据完整性保障
sendMessage
vs. post
对比1. 底层一致性
post(Runnable)
是对 sendMessage()
的封装,将 Runnable
存入 Message.callback
字段。MessageQueue.enqueueMessage()
提交。2. 使用场景对比
特性 | sendMessage(Message) |
post(Runnable) |
---|---|---|
适用场景 | 携带结构化数据、复用消息池 | 快速提交代码块 |
代码简洁性 | 需构建 Message 对象 | 一行内联语法 |
性能差异 | 几乎无差异(可忽略) | 同左 |
3. 开发建议
post()
(简化逻辑)。sendMessage()
更易管理消息池(如频繁发送带参数的消息)。