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() 更易管理消息池(如频繁发送带参数的消息)。