Handler 是 Android 消息驱动模型的核心,也是应用层和系统层之间最关键的线程通信机制。从架构上讲,Handler 涉及 Java 层的 Handler/Looper/MessageQueue/Message 四件套,以及 native 层的 NativeMessageQueue、Looper(native 版)和 epoll 事件循环。本文深入这两层,全面剖析 Handler 的底层运作。
一、Java 层四件套 1.1 整体架构 Handler (发送者 & 处理器) ├── sendMessage(Message) / post(Runnable) │ └── MessageQueue.enqueueMessage(msg, when) │ └── 按 when 排序插入单向链表 │ └── dispatchMessage(Message) ├── msg.callback (Runnable) 优先 ├── mCallback.handleMessage 其次 └── handleMessage 最后 MessageQueue (消息队列) ├── enqueueMessage: 插入消息(按 when 有序) ├── next(): 取消息,无消息时阻塞 └── mIdleHandlers: 空闲时执行 Looper (轮询器) ├── prepare(): 创建 Looper + MessageQueue,绑定线程 └── loop(): 死循环调 MessageQueue.next()
AOSP 核心路径:
frameworks/base/core/java/android/os/Handler.java
frameworks/base/core/java/android/os/Looper.java
frameworks/base/core/java/android/os/MessageQueue.java
frameworks/base/core/java/android/os/Message.java
1.2 ActivityThread 中的主线程 Looper public static void main (String[] args) { Looper.prepareMainLooper(); ActivityThread thread = new ActivityThread (); thread.attach(false , startSeq); if (sMainThreadHandler == null ) { sMainThreadHandler = thread.getHandler(); } Looper.loop(); throw new RuntimeException ("Main thread loop unexpectedly exited" ); }
这里有个关键认知:为什么死循环不卡死 UI 线程?因为消息循环等价于事件驱动模型。UI 线程在没有消息时处于休眠状态(epoll_wait 阻塞),收到消息才被唤醒。所有 UI 操作(触摸事件、刷新、invalidate)都是通过 Handler 发消息来驱动的,这正是 Android 的事件驱动架构。
1.3 Looper 与线程绑定 static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal <Looper>();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)); } private Looper (boolean quitAllowed) { mQueue = new MessageQueue (quitAllowed); mThread = Thread.currentThread(); }
ThreadLocal 的原理是每个线程维护一个独立的 Map(key = ThreadLocal 实例,value = Looper)。因此不同线程的 sThreadLocal.get() 返回的是各自的 Looper。
1.4 MessageQueue.enqueueMessage——消息入队 boolean enqueueMessage (Message msg, long when ) { if (msg.target == null ) { throw new IllegalArgumentException ("Message must have a target." ); } synchronized (this ) { msg.when = when ; Message p = mMessages; boolean needWake; if (p == null || when == 0 || when < p.when ) { msg.next = p; mMessages = msg; needWake = mBlocked; } else { 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 ; }
1.5 MessageQueue.next——消息出队与阻塞 Message next () { int nextPollTimeoutMillis = 0 ; for (;;) { if (nextPollTimeoutMillis != 0 ) { Binder.flushPendingCommands(); } nativePollOnce(mPtr, 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 (pendingIdleHandlerCount < 0 && ...) { mPendingIdleHandlers = mIdleHandlers.toArray(...); } 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); } } } } } }
二、Native 层深入 2.1 Java 层与 Native 层的桥梁 Java 层的 MessageQueue 在构造时通过 JNI 创建 native 层的 NativeMessageQueue:
MessageQueue(boolean quitAllowed) { mQuitAllowed = quitAllowed; mPtr = nativeInit(); }
Native 函数映射:
static jlong android_os_MessageQueue_nativeInit (JNIEnv* env, jclass clazz) { NativeMessageQueue* nativeMessageQueue = new NativeMessageQueue (); if (!nativeMessageQueue) { jniThrowRuntimeException (env, "Unable to allocate native queue" ); return 0 ; } nativeMessageQueue->incStrong (env); return reinterpret_cast <jlong>(nativeMessageQueue); }
2.2 NativeMessageQueue 与 Native Looper NativeMessageQueue::NativeMessageQueue () : mPollObj (NULL ), mPollEnv (NULL ), mExceptionObj (NULL ) { mLooper = Looper::getForThread (); if (mLooper == NULL ) { mLooper = new Looper (false ); Looper::setForThread (mLooper); } }
2.3 nativePollOnce——epoll 事件循环核心 static void android_os_MessageQueue_nativePollOnce (JNIEnv* env, jobject obj, jlong ptr, jint timeoutMillis) { NativeMessageQueue* nativeMessageQueue = reinterpret_cast <NativeMessageQueue*>(ptr); nativeMessageQueue->pollOnce (env, obj, timeoutMillis); } void NativeMessageQueue::pollOnce (JNIEnv* env, jobject pollObj, int timeoutMillis) { mPollEnv = env; mPollObj = pollObj; mLooper->pollOnce (timeoutMillis); mPollObj = NULL ; mPollEnv = NULL ; }
2.4 Native Looper::pollOnce——epoll_wait 这是 Handler 机制最底层的核心:
int Looper::pollOnce (int timeoutMillis, int * outFd, int * outEvents, void ** outData) { int result = 0 ; for (;;) { while (mResponseIndex < mResponses.size ()) { ... } result = pollInner (timeoutMillis); } } int Looper::pollInner (int timeoutMillis) { if (timeoutMillis != 0 && mNextMessageUptime != LLONG_MAX) { nsecs_t now = systemTime (SYSTEM_TIME_MONOTONIC); int messageTimeoutMillis = toMillisecondTimeoutDelay (now, mNextMessageUptime); if (messageTimeoutMillis >= 0 && (timeoutMillis < 0 || messageTimeoutMillis < timeoutMillis)) { timeoutMillis = messageTimeoutMillis; } } struct epoll_event eventItems[EPOLL_MAX_EVENTS]; int eventCount = epoll_wait (mEpollFd.get (), 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 (); } } else { ssize_t requestIndex = mRequests.indexOfKey (fd); if (requestIndex >= 0 ) { int events = 0 ; if (epollEvents & EPOLLIN) events |= EVENT_INPUT; if (epollEvents & EPOLLOUT) events |= EVENT_OUTPUT; if (epollEvents & EPOLLERR) events |= EVENT_ERROR; if (epollEvents & EPOLLHUP) events |= EVENT_HANGUP; pushResponse (events, mRequests.valueAt (requestIndex)); } } } while (mMessageEnvelopes.size () != 0 ) { ... } return result; }
2.5 eventfd——高效的唤醒机制 Native Looper 使用 Linux eventfd 作为唤醒机制:
Looper::Looper (bool allowNonCallbacks) : mAllowNonCallbacks (allowNonCallbacks), mSendingMessage (false ), mPolling (false ), mEpollFd (::epoll_create1 (EPOLL_CLOEXEC)), mEpollRebuildRequired (false ), mNextRequestSeq (0 ), mResponseIndex (0 ), mNextMessageUptime (LLONG_MAX) { mWakeEventFd.reset (eventfd (0 , EFD_NONBLOCK | EFD_CLOEXEC)); int result = addFd (mWakeEventFd.get (), 0 , EPOLLIN, NULL ); } void Looper::wake () { uint64_t inc = 1 ; ssize_t nWrite = TEMP_FAILURE_RETRY ( write (mWakeEventFd.get (), &inc, sizeof (uint64_t ))); }
当 Java 层有新消息入队需要唤醒 epoll_wait 时,调用链是:nativeWake(mPtr) → NativeMessageQueue::wake() → Looper::wake() → write(eventfd, ...) → epoll_wait 被唤醒。
三、同步屏障机制 同步屏障是 Android UI 渲染优化的关键设计。当 View 系统需要刷新 UI 时,它向 MessageQueue 发送一条 target==null 的消息(屏障消息),然后 post 异步消息(如 Choreographer 的 FrameDisplayEventReceiver)。在 next() 方法中,遇到 target==null 的消息时,会跳过所有同步消息,只处理异步消息,从而确保 UI 渲染优先于普通消息处理。
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; 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; } } void removeSyncBarrier (int token) { synchronized (this ) { Message prev = null ; Message p = mMessages; while (p != null && (p.target != null || p.arg1 != token)) { prev = p; p = p.next; } if (p != null ) { if (prev != null ) { prev.next = p.next; } else { mMessages = p.next; } p.recycleUnchecked(); } } }
四、IdleHandler 机制 IdleHandler 是主线程空闲回调机制,常用于性能优化场景:
Looper.myQueue().addIdleHandler(new MessageQueue .IdleHandler() { @Override public boolean queueIdle () { initNonCriticalComponents(); return false ; } });
五、Handler 内存泄漏的源码级分析 泄漏的根本原因在于 Message 持有 Handler 的引用。当一条延迟消息在 MessageQueue 中等待时,其引用链是:
MessageQueue.mMessages → Message → Message.target → Handler → Activity (隐式引用)
如果 Activity 在消息到达前被销毁,但消息还未被处理,Activity 就无法被 GC。
private boolean enqueueMessage (@NonNull MessageQueue queue, @NonNull Message msg, long uptimeMillis) { msg.target = this ; return queue.enqueueMessage(msg, uptimeMillis); }
正确的写法:静态内部类 + WeakReference
static class MyHandler extends Handler { private final WeakReference<Activity> mActivityRef; MyHandler(Activity activity) { mActivityRef = new WeakReference <>(activity); } @Override public void handleMessage (Message msg) { Activity activity = mActivityRef.get(); if (activity == null || activity.isFinishing()) return ; } }
六、核心面试题 Q1:Looper.loop() 是一个死循环,为什么主线程不会卡死?Android 的事件驱动模型和传统阻塞 I/O 模型有什么本质区别?
Looper.loop() 的死循环本质是事件驱动的核心。没有消息时,MessageQueue.next() 通过 native 层的 epoll_wait 进入内核态休眠,CPU 时间片被释放给其他线程。当新消息到达(通过 eventfd 写入唤醒)或 input 事件到达(通过 InputChannel 唤醒)时,epoll_wait 返回,loop 继续处理。这并非忙等(busy-wait),而是一个高效的事件驱动系统。
Q2:Message 的 target 为什么要设计为 Handler 类型?为什么不让 Looper 直接分发到 handlerMessage?
设计为 target 而非 Looper 直接分发有多个好处:(1) 解耦——同一个线程可以有多个 Handler,不同的 Handler 处理不同类型的消息;(2) post(Runnable) 机制——通过 msg.callback 实现 Runnable 的 post,而不需要子类化 Handler;(3) 同步屏障——通过 target==null 可以控制消息优先级(比如 UI 渲染的异步消息优先于同步消息)。
Q3:nativePollOnce 底层用了 epoll,那除了 Handler 的消息唤醒,它还监听哪些 fd 事件?
Native Looper 的 epoll 监听了多个 fd:InputChannel 的 fd(用于接收 InputDispatcher 发送的输入事件)、eventfd(Java 层消息插入时的唤醒)、以及由 addFd() 注册的其他 fd(如某些 Native 组件的通信管道)。这也就是为什么 Looper 不仅能处理 Handler 消息,还能响应触摸/按键事件。
AOSP 核心路径参考:
frameworks/base/core/java/android/os/Handler.java
frameworks/base/core/java/android/os/Looper.java
frameworks/base/core/java/android/os/MessageQueue.java
frameworks/base/core/java/android/os/Message.java
frameworks/base/core/jni/android_os_MessageQueue.cpp
system/core/libutils/Looper.cpp
system/core/libutils/include/utils/Looper.h