一、Handler 的作用
| 作用 | 说明 |
|---|---|
| 线程间通信 | 子线程发送消息到主线程,更新 UI |
| 定时/延时执行 | 延迟发送消息或定时重复任务 |
| 任务调度 | 将任务投递到指定线程的 Looper 中排队执行 |
二、核心原理
四组件协作

| 组件 | 职责 |
|---|---|
| Handler | 发送消息(sendMessage/post)、处理消息(handleMessage/Runnable) |
| Message | 承载数据(what、arg1、arg2、obj)、目标 Handler(target)、回调(callback) |
| MessageQueue | 按执行时间排序的链表队列,管理消息的入队/出队 |
| Looper | 通过 ThreadLocal 绑定线程,无限循环从队列取消息分发 |
关键源码
Looper.prepare() --- 创建并绑定线程
java
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<>();
public static void prepare() {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
Looper.loop() --- 无限循环
java
public static void loop() {
final Looper me = myLooper();
final MessageQueue queue = me.mQueue;
for (;;) { // 死循环
Message msg = queue.next(); // 阻塞等待(epoll_wait)
if (msg == null) return;
msg.target.dispatchMessage(msg); // 分发到 Handler
msg.recycleUnchecked(); // 回收复用
}
}
MessageQueue.next() --- 阻塞与唤醒
java
Message next() {
for (;;) {
nativePollOnce(ptr, nextPollTimeoutMillis); // epoll 阻塞,线程休眠
synchronized (this) {
Message msg = mMessages;
if (msg != null) {
if (now < msg.when) {
nextPollTimeoutMillis = (int)(msg.when - now); // 计算等待时间
} else {
mMessages = msg.next; // 取出消息
return msg;
}
}
}
}
}
Handler.sendMessage() --- 入队并唤醒
java
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
msg.target = this; // 标记目标 Handler
return queue.enqueueMessage(msg, uptimeMillis);
}
// MessageQueue.enqueueMessage
boolean enqueueMessage(Message msg, long when) {
synchronized (this) {
// 按时间插入链表
// ...
if (needWake) {
nativeWake(mPtr); // 写入 eventfd,唤醒 epoll_wait
}
}
}
Handler.dispatchMessage() --- 三种回调优先级
java
public void dispatchMessage(Message msg) {
if (msg.callback != null) { // 优先级1:post(Runnable) 的 callback
handleCallback(msg);
} else {
if (mCallback != null) { // 优先级2:构造时的 Callback 接口
if (mCallback.handleMessage(msg)) return;
}
handleMessage(msg); // 优先级3:子类重写的方法
}
}
三、典型应用
1. 子线程更新 UI
java
new Thread(() -> {
final String result = loadData();
new Handler(Looper.getMainLooper()).post(() -> {
textView.setText(result);
});
}).start();
2. 延时/定时任务
java
Handler handler = new Handler(Looper.getMainLooper());
// 延时 3 秒
handler.postDelayed(() -> hideLoading(), 3000);
// 定时轮询
Runnable task = new Runnable() {
public void run() {
refresh();
handler.postDelayed(this, 5000);
}
};
handler.postDelayed(task, 5000);
3. HandlerThread --- 自带 Looper 的工作线程
java
HandlerThread thread = new HandlerThread("Worker");
thread.start();
Handler worker = new Handler(thread.getLooper()) {
@Override
public void handleMessage(Message msg) {
// 在 Worker 线程执行耗时操作
}
};
worker.sendEmptyMessage(1);
4. 系统框架中的 Handler
| 场景 | 作用 |
|---|---|
| ActivityThread | 主线程消息循环,处理四大组件生命周期回调 |
| ViewRootImpl | 通过 Choreographer 调度 UI 绘制(measure/layout/draw) |
| Choreographer | 接收 VSYNC 信号,同步屏障保障绘制优先 |
| Binder 线程 | ApplicationThread 通过 Handler 将 IPC 回调切换到主线程 |
四、王者地位
Handler 在 Android 中的地位是 "线程通信的基石,消息驱动的灵魂 "。整个 Android 系统框架几乎建立在 Handler + Looper + MessageQueue 这套消息机制之上。
1. 系统框架中的核心地位
1.1 主线程的生命线
java
// ActivityThread.java ------ App 启动入口
public static void main(String[] args) {
Looper.prepareMainLooper(); // 创建主线程 Looper
ActivityThread thread = new ActivityThread();
thread.attach(false, startSeq);
// 获取主线程 Handler
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler(); // H 类 Handler
}
Looper.loop(); // 进入消息循环,永不退出
}
没有 Handler/Looper,主线程无法运行,App 直接崩溃。
1.2 四大组件的生命周期调度
所有 Activity、Service、BroadcastReceiver 的生命周期回调,都是通过 ActivityThread.H 这个 Handler 分发到主线程的:
java
// ActivityThread.java 内部类 H
class H extends Handler {
public static final int LAUNCH_ACTIVITY = 100;
public static final int PAUSE_ACTIVITY = 101;
public static final int STOP_ACTIVITY_SHOW = 103;
public static final int RESUME_ACTIVITY = 107;
public static final int DESTROY_ACTIVITY = 109;
public static final int BIND_APPLICATION = 110;
public static final int EXIT_APPLICATION = 111;
public static final int RECEIVER = 113;
public static final int CREATE_SERVICE = 114;
public static final int SERVICE_ARGS = 115;
public static final int STOP_SERVICE = 116;
// ... 更多
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case LAUNCH_ACTIVITY:
handleLaunchActivity((ActivityClientRecord) msg.obj);
break;
case PAUSE_ACTIVITY:
handlePauseActivity((IBinder) msg.obj);
break;
case RESUME_ACTIVITY:
handleResumeActivity((IBinder) msg.obj);
break;
// ... 所有生命周期方法都在这里
}
}
}
Binder 线程收到 AMS 的 IPC 调用 → 封装成 Message → 通过 H Handler 切换到主线程执行。
1.3. View 的绘制与事件分发
java
// ViewRootImpl.java
final ViewRootHandler mHandler = new ViewRootHandler();
// 申请 UI 绘制
void scheduleTraversals() {
if (!mTraversalScheduled) {
mTraversalScheduled = true;
// 同步屏障:阻塞普通消息,保障绘制优先
mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
// 通过 Choreographer 注册 VSYNC 回调
mChoreographer.postCallback(Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
}
}
// 执行 measure / layout / draw
final class TraversalRunnable implements Runnable {
public void run() {
doTraversal();
}
}
没有 Handler,View 无法绘制,屏幕永远是黑的。
1.4. 输入事件的流转
java
// Input 事件流程
InputDispatcher (Native, system_server)
↓ 通过 InputChannel (SocketPair)
InputEventReceiver (App, 子线程)
↓ 封装成 Message
NativeInputEventReceiver → ViewRootImpl.mHandler
↓ 切换到主线程
DecorView.dispatchTouchEvent() → Activity.dispatchTouchEvent()
↓
ViewGroup.dispatchTouchEvent() → 子 View
Input 事件从底层到应用层,最终通过 Handler 切换到主线程处理。
2. 与其他核心机制的关联
| 机制 | Handler 的作用 |
|---|---|
| Binder IPC | ApplicationThread 通过 Handler 将 AMS 的 IPC 回调切换到主线程 |
| Choreographer | 基于 Handler + 同步屏障 + VSYNC 实现帧调度 |
| AsyncTask | 底层使用 InternalHandler 切换线程 |
| LiveData | 通过 Dispatchers.Main 或 Handler 确保主线程更新 |
| RxJava | AndroidSchedulers.mainThread() 内部使用 Handler |
| 协程 (Kotlin) | Dispatchers.Main 基于 Handler 实现 |
| Jetpack 组件 | ViewModel、Room 等异步回调通过 Handler 切回主线程 |
3. 地位

五、常见问题
1. 内存泄漏
原因: 非静态内部类持有外部 Activity 引用,延迟消息未执行时 Activity 无法回收。
java
// 错误写法
private Handler mHandler = new Handler() { // 匿名内部类持有 Activity
public void handleMessage(Message msg) {
textView.setText("..."); // 持有 Activity 引用链
}
};
mHandler.sendEmptyMessageDelayed(1, 10 * 60 * 1000); // 10分钟后执行
解决方案:
java
// 静态内部类 + WeakReference
private static class SafeHandler extends Handler {
private final WeakReference<Activity> mRef;
SafeHandler(Activity activity) {
mRef = new WeakReference<>(activity);
}
@Override
public void handleMessage(Message msg) {
Activity activity = mRef.get();
if (activity == null || activity.isFinishing()) return;
// 处理消息
}
}
// 同时 onDestroy 中移除消息
@Override
protected void onDestroy() {
super.onDestroy();
mHandler.removeCallbacksAndMessages(null);
}
2. 子线程创建 Handler 崩溃
java
// 错误:子线程默认没有 Looper
new Thread(() -> {
new Handler(); // RuntimeException: No Looper
}).start();
// 正确:手动创建 Looper
new Thread(() -> {
Looper.prepare();
Handler handler = new Handler();
Looper.loop();
}).start();
3. 主线程 loop() 是死循环,为什么没 ANR?
Looper.loop() 的 for(;😉 本身不会导致 ANR。ANR是因为消息处理耗时过长,阻塞了后续消息(如输入事件、绘制消息)。
java
// 不会 ANR:loop 只是循环取消息
for (;;) {
Message msg = queue.next(); // 无消息时 epoll 阻塞,线程休眠,不耗 CPU
msg.target.dispatchMessage(msg); // ANR 发生在这里:处理耗时
}
4. Message.obtain() vs new Message()
java
// 推荐:从消息池复用,避免 GC
Message msg = Message.obtain();
msg.what = 1;
handler.sendMessage(msg);
// 不推荐:频繁创建对象
Message msg = new Message(); // 每次 new,增加 GC 压力
5. postDelayed 不准确
延迟时间是入队时间,不是精确的执行时间。如果消息队列前面有耗时消息,实际执行会延后。
6. 同步屏障(Sync Barrier)是什么?
系统框架内部机制,阻塞所有同步消息,只允许异步消息通过。用于保障 Choreographer 的 UI 绘制(CALLBACK_TRAVERSAL)优先执行,避免掉帧。应用层无法直接调用。
六、总结
-
Handler = 线程间邮差。把任务打包成 Message,投递到目标线程的 MessageQueue,由 Looper 按顺序取出,回调 Handler 执行。底层通过 ThreadLocal 实现线程隔离,通过 epoll + eventfd 实现阻塞与唤醒。
-
Handler 是 Android 的"神经系统"------没有它,主线程无法呼吸,组件无法存活,UI 无法绘制,App 就是一具空壳。