在理解Handler基本使用后,我们深入源码层面分析其运行机制。本部分将追踪消息从发送到处理的完整流程,揭示Android消息系统的精妙设计。
一、核心源码类结构
1. Message(消息载体)
public final class Message implements Parcelable {
public int what; // 消息标识
public int arg1; // 整型参数1
public int arg2; // 整型参数2
public Object obj; // 任意对象
long when; // 执行时间戳
Bundle data; // 数据Bundle
Handler target; // 目标Handler
Runnable callback; // Runnable回调
Message next; // 链表指针
static Message sPool; // 对象池
static int sPoolSize; // 对象池大小
}
关键设计:
- 链表结构:组成MessageQueue的链表
- 对象池:静态池复用消息对象(MAX_POOL_SIZE=50)
- 状态标记:FLAG_IN_USE标记使用中状态
2. Handler(消息处理器)
public class Handler {
final Looper mLooper; // 关联的Looper
final MessageQueue mQueue; // 关联的消息队列
final Callback mCallback; // 回调接口
// 核心发送方法
public final boolean sendMessageDelayed(Message msg, long delayMillis) {
// 最终调用enqueueMessage
}
// 消息入队
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this; // 关键绑定
return queue.enqueueMessage(msg, uptimeMillis);
}
// 消息分发
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg); // 处理Runnable
} else {
if (mCallback != null && mCallback.handleMessage(msg)) {
return;
}
handleMessage(msg); // 虚方法处理
}
}
}
3. Looper(消息循环器)
public final class Looper {
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<>();
final MessageQueue mQueue; // 关联的消息队列
final Thread mThread; // 绑定线程
// 准备当前线程的Looper
public static void prepare() {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper per thread");
}
sThreadLocal.set(new Looper());
}
// 核心循环方法
public static void loop() {
final Looper me = myLooper();
final MessageQueue queue = me.mQueue;
for (;;) {
Message msg = queue.next(); // 阻塞获取消息
if (msg == null) return; // 退出信号
try {
msg.target.dispatchMessage(msg); // 分发处理
} finally {
msg.recycleUnchecked(); // 回收消息
}
}
}
}
4. MessageQueue(消息队列)
public final class MessageQueue {
private long mPtr; // Native层指针
Message mMessages; // 消息链表头
private boolean mQuitting; // 退出标志
// 核心入队方法
boolean enqueueMessage(Message msg, long when) {
synchronized (this) {
// 按执行时间排序插入链表
msg.when = when;
Message p = mMessages;
if (p == null || when < p.when) {
// 插入链表头部
msg.next = p;
mMessages = msg;
} else {
// 查找插入位置
Message prev;
do {
prev = p;
p = p.next;
} while (p != null && when >= p.when);
msg.next = p;
prev.next = msg;
}
// 唤醒队列
if (needWake) nativeWake(mPtr);
}
return true;
}
// 核心出队方法
Message next() {
for (;;) {
nativePollOnce(ptr, nextPollTimeoutMillis); // Native阻塞
synchronized (this) {
// 获取当前时间
final long now = SystemClock.uptimeMillis();
Message prevMsg = null;
Message msg = mMessages;
// 处理同步屏障
if (msg != null && msg.target == null) {
do {
prevMsg = msg;
msg = msg.next;
} while (msg != null && !msg.isAsynchronous());
}
if (msg != null) {
if (now < msg.when) {
// 计算等待时间
nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
} else {
// 取出消息
if (prevMsg != null) prevMsg.next = msg.next;
else mMessages = msg.next;
msg.next = null;
return msg;
}
} else {
nextPollTimeoutMillis = -1; // 无限等待
}
// 处理退出
if (mQuitting) return null;
// 处理IdleHandler
if (pendingIdleHandlerCount > 0) {
for (int i = 0; i < pendingIdleHandlerCount; i++) {
idler.queueIdle(); // 执行空闲任务
}
}
}
}
}
}
二、核心流程源码追踪
1. 消息发送流程(以sendMessageDelayed为例)
// Handler.java
public final boolean sendMessageDelayed(Message msg, long delayMillis) {
if (delayMillis < 0) delayMillis = 0;
// 计算执行时间戳
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;
return enqueueMessage(queue, msg, uptimeMillis);
}
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this; // 关键:绑定当前Handler
if (mAsynchronous) msg.setAsynchronous(true);
return queue.enqueueMessage(msg, uptimeMillis); // 转入消息队列
}
2. 消息入队排序(MessageQueue.enqueueMessage)
boolean enqueueMessage(Message msg, long when) {
synchronized (this) {
msg.markInUse();
msg.when = when;
Message p = mMessages;
boolean needWake;
// 链表插入逻辑
if (p == null || when == 0 || when < p.when) {
// 插入链表头部
msg.next = p;
mMessages = msg;
needWake = mBlocked; // 需要唤醒
} else {
// 插入链表中间或尾部
needWake = mBlocked && p.target == null && msg.isAsynchronous();
Message prev;
for (;;) {
prev = p;
p = p.next;
if (p == null || when < p.when) break;
}
msg.next = p;
prev.next = msg;
}
// 唤醒机制
if (needWake) nativeWake(mPtr);
}
return true;
}
3. 消息循环获取(MessageQueue.next)
Message next() {
int nextPollTimeoutMillis = 0;
for (;;) {
// 阻塞等待(JNI调用epoll)
nativePollOnce(ptr, nextPollTimeoutMillis);
synchronized (this) {
final long now = SystemClock.uptimeMillis();
Message prevMsg = null;
Message msg = mMessages;
// 同步屏障处理(系统级特性)
if (msg != null && msg.target == null) {
do {
prevMsg = msg;
msg = msg.next;
} while (msg != null && !msg.isAsynchronous());
}
if (msg != null) {
if (now < msg.when) {
// 计算等待时间
nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
} else {
// 取出消息
mBlocked = false;
if (prevMsg != null) prevMsg.next = msg.next;
else mMessages = msg.next;
msg.next = null;
msg.markInUse();
return msg; // 返回有效消息
}
} else {
nextPollTimeoutMillis = -1; // 无消息时无限等待
}
// 处理退出请求
if (mQuitting) {
dispose();
return null;
}
// 空闲任务处理
if (pendingIdleHandlerCount <= 0) {
mBlocked = true;
continue;
}
// 执行IdleHandler
for (int i = 0; i < pendingIdleHandlerCount; i++) {
idler.queueIdle();
}
}
}
}
4. 消息分发处理(Handler.dispatchMessage)
public void dispatchMessage(Message msg) {
// 处理优先级:
// 1. Message自带的Runnable
// 2. Handler的Callback
// 3. Handler子类的handleMessage
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) return;
}
handleMessage(msg);
}
}
private static void handleCallback(Message message) {
message.callback.run(); // 直接执行Runnable
}
5. 消息回收机制
// Looper.loop()
try {
msg.target.dispatchMessage(msg);
} finally {
msg.recycleUnchecked(); // 回收消息
}
// Message.java
void recycleUnchecked() {
// 重置所有字段
flags = FLAG_IN_USE;
what = 0;
arg1 = 0;
arg2 = 0;
obj = null;
...
// 加入对象池
synchronized (sPoolSync) {
if (sPoolSize < MAX_POOL_SIZE) {
next = sPool;
sPool = this;
sPoolSize++;
}
}
}
三、关键技术点解析
1. 阻塞唤醒机制(epoll模型)
// native方法实现 (android_os_MessageQueue.cpp)
static void android_os_MessageQueue_nativePollOnce(JNIEnv* env, jobject obj, jlong ptr, jint timeoutMillis) {
NativeMessageQueue* nativeQueue = reinterpret_cast<NativeMessageQueue*>(ptr);
nativeQueue->pollOnce(env, obj, timeoutMillis);
}
void NativeMessageQueue::pollOnce(JNIEnv* env, jobject pollObj, int timeoutMillis) {
mInCallback = true;
mLooper->pollOnce(timeoutMillis); // 调用Looper的pollOnce
mInCallback = false;
}
// 系统Looper的pollOnce
int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
int result = 0;
for (;;) {
// 处理所有事件
while (mResponseIndex < mResponses.size()) {
...
}
if (result != 0) return result;
// 核心epoll_wait
int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);
// 处理事件
for (int i = 0; i < eventCount; i++) {
int fd = eventItems[i].data.fd;
uint32_t epollEvents = eventItems[i].events;
if (fd == mWakeEventFd.get()) {
if (epollEvents & EPOLLIN) {
awoken(); // 读取唤醒事件
}
}
}
}
}
阻塞唤醒流程:
- 当消息队列为空时,调用
epoll_wait进入阻塞状态 - 新消息入队时(特别当插入到队列头部),调用
nativeWake - 向
mWakeEventFd写入数据,触发epoll事件 epoll_wait返回,线程继续执行
2. 同步屏障机制(Sync Barrier)
// 系统级方法(应用层通常不直接使用)
public int postSyncBarrier() {
return postSyncBarrier(SystemClock.uptimeMillis());
}
private int postSyncBarrier(long when) {
synchronized (this) {
final int token = mNextBarrierToken++;
final Message msg = Message.obtain();
msg.markInUse();
msg.when = when;
msg.arg1 = token;
// 关键:target=null 标识为屏障
Message prev = null;
Message p = mMessages;
// 按时间顺序插入屏障
if (when != 0) {
while (p != null && p.when <= when) {
prev = p;
p = p.next;
}
}
if (prev != null) {
msg.next = p;
prev.next = msg;
} else {
msg.next = p;
mMessages = msg;
}
return token;
}
}
屏障工作原理:
-
插入target=null的特殊消息
-
在
next()方法中遇到屏障时:- 跳过所有同步消息(isAsynchronous()=false)
- 只处理异步消息(通常用于VSYNC等系统事件)
-
通过
removeSyncBarrier()移除屏障
3. 空闲处理机制(IdleHandler)
// 使用示例
Looper.myQueue().addIdleHandler(new MessageQueue.IdleHandler() {
@Override
public boolean queueIdle() {
// 执行低优先级任务
return false; // true=保留,false=移除
}
});
// MessageQueue实现
void addIdleHandler(@NonNull IdleHandler handler) {
synchronized (this) {
mIdleHandlers.add(handler);
}
}
// next()方法中
if (pendingIdleHandlerCount < 0
&& (mMessages == null || now < mMessages.when)) {
pendingIdleHandlerCount = mIdleHandlers.size();
}
if (pendingIdleHandlerCount <= 0) {
mBlocked = true;
continue;
}
for (int i = 0; i < pendingIdleHandlerCount; i++) {
final IdleHandler idler = mPendingIdleHandlers[i];
mPendingIdleHandlers[i] = null;
boolean keep = false;
try {
keep = idler.queueIdle(); // 执行空闲任务
} catch (Throwable t) { /* 异常处理 */ }
if (!keep) {
synchronized (this) {
mIdleHandlers.remove(idler);
}
}
}
空闲处理特点:
- 仅在消息队列空闲时执行
- 适合执行低优先级后台任务
- 避免在主线程繁忙时增加负担
4. 主线程消息循环启动
// ActivityThread.java
public static void main(String[] args) {
// 1. 准备主线程Looper
Looper.prepareMainLooper();
// 2. 创建ActivityThread
ActivityThread thread = new ActivityThread();
thread.attach(false);
// 3. 启动主循环
Looper.loop();
throw new RuntimeException("Main thread loop exited unexpectedly");
}
主线程特殊处理:
prepareMainLooper()设置不可退出的Looper- 通过
ActivityThread.H处理系统消息 - View绘制、Activity生命周期等均通过此消息队列处理
四、内存管理最佳实践
1. 避免内存泄漏方案
静态内部类 + WeakReference:
private static class SafeHandler extends Handler {
private final WeakReference<Activity> mActivityRef;
SafeHandler(Activity activity) {
mActivityRef = new WeakReference<>(activity);
}
@Override
public void handleMessage(Message msg) {
Activity activity = mActivityRef.get();
if (activity == null || activity.isFinishing()) {
return;
}
// 安全处理消息
}
}
// Activity中
private final Handler mHandler = new SafeHandler(this);
2. 生命周期同步
@Override
protected void onDestroy() {
super.onDestroy();
// 1. 移除所有回调
mHandler.removeCallbacksAndMessages(null);
// 2. 退出后台线程Looper
if (mWorkerThread != null) {
mWorkerThread.quitSafely();
}
}
五、设计思想总结
-
生产者-消费者模型
- 生产者:各种线程通过Handler发送消息
- 缓冲区:MessageQueue消息队列
- 消费者:Looper循环处理
-
线程隔离设计
- ThreadLocal保证线程局部存储
- 消息处理严格在创建线程执行
-
高效资源管理
- Message对象池减少GC
- epoll机制实现精准唤醒
- 时间排序优化消息获取
-
优先级调度
- 同步屏障处理紧急任务
- 空闲处理低优先级任务
- 延时消息精确调度
-
系统级集成
- 主线程消息循环驱动整个APP
- View绘制、输入事件均通过此机制
六、性能优化建议
-
减少消息数量
- 合并UI更新消息
- 使用
postAtFrontOfQueue谨慎
-
优化消息对象
- 始终使用
Message.obtain() - 避免在消息中传递大对象
- 始终使用
-
合理使用延迟
- 避免高频发送延迟消息
- 及时移除无用延迟消息
-
监控队列状态
// 检查主线程阻塞 Looper.getMainLooper().setMessageLogging(logger); // 自定义Printer监控 public class BlockDetectPrinter implements Printer { private long lastLogTime = 0; @Override public void println(String x) { if (x.startsWith(">>>>>")) { lastLogTime = System.currentTimeMillis(); } else { long cost = System.currentTimeMillis() - lastLogTime; if (cost > 100) { // 主线程阻塞警告 } } } }