Android Handler机制详解(源码分析篇)

112 阅读7分钟

在理解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(); // 读取唤醒事件
                }
            }
        }
    }
}

阻塞唤醒流程:

  1. 当消息队列为空时,调用epoll_wait进入阻塞状态
  2. 新消息入队时(特别当插入到队列头部),调用nativeWake
  3. mWakeEventFd写入数据,触发epoll事件
  4. 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;
    }
}

屏障工作原理:

  1. 插入target=null的特殊消息

  2. next()方法中遇到屏障时:

    • 跳过所有同步消息(isAsynchronous()=false)
    • 只处理异步消息(通常用于VSYNC等系统事件)
  3. 通过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();
    }
}

五、设计思想总结

  1. 生产者-消费者模型

    • 生产者:各种线程通过Handler发送消息
    • 缓冲区:MessageQueue消息队列
    • 消费者:Looper循环处理
  2. 线程隔离设计

    • ThreadLocal保证线程局部存储
    • 消息处理严格在创建线程执行
  3. 高效资源管理

    • Message对象池减少GC
    • epoll机制实现精准唤醒
    • 时间排序优化消息获取
  4. 优先级调度

    • 同步屏障处理紧急任务
    • 空闲处理低优先级任务
    • 延时消息精确调度
  5. 系统级集成

    • 主线程消息循环驱动整个APP
    • View绘制、输入事件均通过此机制

六、性能优化建议

  1. 减少消息数量

    • 合并UI更新消息
    • 使用postAtFrontOfQueue谨慎
  2. 优化消息对象

    • 始终使用Message.obtain()
    • 避免在消息中传递大对象
  3. 合理使用延迟

    • 避免高频发送延迟消息
    • 及时移除无用延迟消息
  4. 监控队列状态

    // 检查主线程阻塞
    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) {
                    // 主线程阻塞警告
                }
            }
        }
    }