深入浅出安卓Handler机制原理

198 阅读3分钟

深入浅出安卓Handler机制原理

一、Handler是啥?

Handler就像安卓的快递小哥

  • 工作职责:在主线程和其他线程之间传递消息(Message)
  • 核心作用:解决"子线程不能更新UI"的问题
  • 工作流程:发送消息 → 排队 → 处理消息

二、Handler四件套

graph TD
    A[Message] --> B[MessageQueue]
    B --> C[Looper]
    C --> D[Handler]

1. Message(快递包裹)

  • what:消息类型标识(像快递单号)
  • arg1/arg2:简单数据(像小件物品)
  • obj:复杂对象(像大件包裹)
  • target:指定处理人(Handler)

2. MessageQueue(快递仓库)

  • 特点:单向链表,按时间排序
  • 关键操作
    • enqueueMessage():存包裹
    • next():取包裹(可能阻塞)

3. Looper(快递分拣员)

  • 职责
    • 不断从MessageQueue取消息
    • 分发给对应的Handler
  • 重要方法
    • prepare():创建Looper
    • loop():开始循环处理

4. Handler(快递小哥)

  • 两大功能
    • sendMessage():发送消息
    • handleMessage():处理消息

三、Handler工作流程

sequenceDiagram
    子线程->>MessageQueue: 1. 发送Message
    Looper->>MessageQueue: 2. 循环检查新消息
    MessageQueue->>Looper: 3. 返回待处理消息
    Looper->>Handler: 4. 分发消息
    Handler->>主线程: 5. 处理消息更新UI

四、源码关键点解析

1. Looper.prepare()

// 创建Looper并绑定到当前线程
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<>();

private static void prepare(boolean quitAllowed) {
    if (sThreadLocal.get() != null) {
        throw new RuntimeException("只能有一个Looper");
    }
    sThreadLocal.set(new Looper(quitAllowed));
}

2. Looper.loop()

public static void loop() {
    final Looper me = myLooper(); // 获取当前线程Looper
    final MessageQueue queue = me.mQueue;
    
    for (;;) { // 死循环
        Message msg = queue.next(); // 可能阻塞
        if (msg == null) return;
        
        msg.target.dispatchMessage(msg); // 交给Handler处理
        msg.recycle(); // 消息回收
    }
}

3. Handler发送消息

// 最终都会走到这里
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
    msg.target = this; // 设置处理者
    return queue.enqueueMessage(msg, uptimeMillis);
}

五、使用示例

1. 主线程创建Handler

// 主线程默认有Looper
Handler handler = new Handler(Looper.getMainLooper()) {
    @Override
    public void handleMessage(Message msg) {
        // 在这里更新UI
        textView.setText((String)msg.obj);
    }
};

// 子线程发送消息
new Thread(() -> {
    Message msg = handler.obtainMessage();
    msg.obj = "来自子线程的消息";
    handler.sendMessage(msg);
}).start();

2. 子线程创建Handler

new Thread(() -> {
    Looper.prepare(); // 初始化Looper
    
    Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            // 处理消息
        }
    };
    
    Looper.loop(); // 开始循环
}).start();

六、常见问题

1. 为什么主线程不会卡死?

  • 真相:Looper的阻塞被系统事件唤醒
    • 当没有消息时:nativePollOnce()进入休眠
    • 当有新消息时:通过pipe写入数据唤醒

2. Handler内存泄漏

危险代码

Handler handler = new Handler() { /*...*/ }; // 匿名内部类隐式持有Activity引用

正确做法

// 1. 静态内部类+弱引用
static class SafeHandler extends Handler {
    private WeakReference<Activity> weakActivity;
    
    SafeHandler(Activity activity) {
        this.weakActivity = new WeakReference<>(activity);
    }
    
    @Override
    public void handleMessage(Message msg) {
        Activity activity = weakActivity.get();
        if (activity != null) {
            // 安全处理
        }
    }
}

// 2. 在onDestroy移除回调
@Override
protected void onDestroy() {
    super.onDestroy();
    handler.removeCallbacksAndMessages(null);
}

3. 为什么子线程默认没有Looper?

  • 设计考量:减少资源消耗
  • 解决方案
    • 手动调用Looper.prepare()
    • 使用HandlerThread(自带Looper)

七、Handler高级用法

1. 定时任务

// 延迟1秒执行
handler.postDelayed(() -> {
    // do something
}, 1000);

// 循环执行
handler.postDelayed(new Runnable() {
    @Override
    public void run() {
        // do something
        handler.postDelayed(this, 1000); // 再次提交
    }
}, 1000);

2. 同步屏障(Sync Barrier)

// 插入屏障(优先处理异步消息)
MessageQueue queue = Looper.getMainLooper().getQueue();
Method method = queue.getClass().getDeclaredMethod("postSyncBarrier");
int token = (int) method.invoke(queue);

// 移除屏障
Method removeMethod = queue.getClass().getDeclaredMethod("removeSyncBarrier", int.class);
removeMethod.invoke(queue, token);

八、Handler与多线程

场景解决方案
子线程更新UIhandler.sendMessage()
线程间通信各自持有对方的Handler
定时任务postDelayed()
任务取消removeCallbacks()

九、终极原理口诀

"Handler机制四件套,各司其职配合妙
Message像快递包裹,Queue是仓库保管好
Looper像分拣员,循环取件不睡觉
Handler就是快递员,送货上门效率高
主线程默认配Looper,子线程需自备好
内存泄漏要当心,弱引用加及时清掉"

理解Handler机制,你就能掌握安卓线程通信的精髓! 📨➡️📱