当前位置: 首页 > news >正文

Android Handler 线程执行机制

在 Android 中,Handler 中的代码是由创建该 Handler 时绑定的 Looper 所在的线程执行的。这是 Android 线程通信模型的核心机制,下面我将详细解释其原理和使用场景。

核心原理图解

执行场景分析

1. 主线程 Handler(UI 线程)

// 在主线程创建
Handler mainHandler = new Handler(Looper.getMainLooper());// 在任何线程发送任务
new Thread(() -> {mainHandler.post(() -> {// 这段代码在主线程执行textView.setText("Updated from UI thread");});
}).start();

特点

  • 使用 Looper.getMainLooper() 绑定主线程

  • 适合更新 UI

  • 执行线程:主线程(UI 线程)

2. 子线程 Handler(工作线程)

// 创建带 Looper 的工作线程
HandlerThread workerThread = new HandlerThread("Worker");
workerThread.start();// 绑定工作线程的 Looper
Handler workerHandler = new Handler(workerThread.getLooper());// 发送任务
workerHandler.post(() -> {// 这段代码在 workerThread 执行performLongOperation(); // 耗时操作
});

特点

  • 绑定特定子线程的 Looper

  • 适合后台任务

  • 执行线程:创建 Looper 的子线程

3. 当前线程 Handler

new Thread(() -> {Looper.prepare(); // 初始化当前线程的 LooperHandler threadHandler = new Handler(); // 默认绑定当前线程threadHandler.post(() -> {// 在当前子线程执行Log.d("CurrentThread", Thread.currentThread().getName());});Looper.loop(); // 启动消息循环
}).start();

特点

  • 默认绑定创建 Handler 的线程

  • 需要手动 Looper.prepare() 和 Looper.loop()

  • 执行线程:创建 Handler 的线程

底层机制详解

消息处理流程

关键源码分析

// Handler.java
public void dispatchMessage(Message msg) {if (msg.callback != null) {// 执行 Runnablemsg.callback.run(); // 在Looper所在线程执行} else {if (mCallback != null) {if (mCallback.handleMessage(msg)) {return;}}handleMessage(msg); // 在Looper所在线程执行}
}// Looper.java
public static void loop() {final Looper me = myLooper();final MessageQueue queue = me.mQueue;for (;;) {Message msg = queue.next();if (msg == null) {return;}// 关键:在Looper所在线程执行msg.target.dispatchMessage(msg);}
}

执行线程判断表

Handler 创建方式代码执行线程典型使用场景
new Handler(Looper.getMainLooper())主线程UI 更新
new Handler(handlerThread.getLooper())指定子线程后台任务处理
new Handler()(在主线程)主线程默认 UI 处理
new Handler()(在子线程 + Looper)创建 Handler 的子线程线程内任务调度
view.post(runnable)主线程View 相关操作

常见问题与解决方案

Q:如何在子线程更新 UI?

// 方案1:使用主线程 Handler
new Thread(() -> {// 后台工作runOnUiThread(() -> {// 在主线程更新 UItextView.setText("Done");});
}).start();// 方案2:使用 View.post()
imageView.post(() -> {imageView.setImageBitmap(bitmap);
});

Q:Handler 内存泄漏

// 正确做法:静态内部类 + 弱引用
private static class SafeHandler extends Handler {private final WeakReference<Activity> weakActivity;SafeHandler(Activity activity) {super(Looper.getMainLooper()); // 明确绑定主线程this.weakActivity = new WeakReference<>(activity);}@Overridepublic void handleMessage(Message msg) {Activity activity = weakActivity.get();if (activity != null) {// 安全操作}}
}

常见用法

  1. 明确指定 Looper

    // 总是显式指定 Looper
    new Handler(Looper.getMainLooper()); // 不依赖创建位置
  2. UI 操作使用主线程 Handler

    // 专用 UI Handler
    private final Handler uiHandler = new Handler(Looper.getMainLooper());void updateUI(String text) {uiHandler.post(() -> textView.setText(text));
    }
  3. 后台任务使用工作 Handler

    // 创建工作线程 Handler
    private Handler workerHandler;void initWorker() {HandlerThread thread = new HandlerThread("Worker");thread.start();workerHandler = new Handler(thread.getLooper());
    }void processData(Data data) {workerHandler.post(() -> {// 耗时操作});
    }
  4. 避免在子线程创建无 Looper 的 Handler

    // 错误示例(会崩溃)
    new Thread(() -> {Handler handler = new Handler(); // 抛出异常!
    }).start();

总结

Handler 中的代码在哪个线程执行?

Handler 中的代码执行线程取决于创建 Handler 时绑定的 Looper:

  1. 主线程执行

    • 使用 new Handler(Looper.getMainLooper()) 创建

    • 通过 View.post() 发送的任务

    • 在主线程创建的默认 Handler

  2. 子线程执行

    • 绑定子线程 Looper 的 Handler(如 HandlerThread)

    • 在子线程创建并初始化了 Looper 的 Handler

  3. 执行机制

    • 所有发送到 Handler 的消息/任务,都会被放入关联的 MessageQueue

    • Looper 在绑定线程中不断循环取出消息

    • 最终在 Looper 所在线程执行 dispatchMessage()

http://www.lryc.cn/news/625045.html

相关文章:

  • flutter项目适配鸿蒙
  • 【展厅多媒体】互动地砖屏怎么提升展厅互动感的?
  • 2025年最新美区Apple ID共享账号免费分享(持续更新)
  • 数组学习2
  • Java面试题储备14: 使用aop实现全局日志打印
  • 【HTML】document api
  • Vue 3中watch的返回值:解锁监听的隐藏技巧
  • C++---有符号和无符号整数的位移操作
  • RabbitMQ:数据隔离
  • kafka 冲突解决 kafka安装
  • Unity进阶--C#补充知识点--【Unity跨平台的原理】Mono与IL2CPP
  • 探索性测试:灵活找Bug的“人肉探测仪”
  • MongoDB Windows 系统实战手册:从配置到数据处理入门
  • keil错误:Error: failed to execute ‘D:\Keil\C51\BIN\BIN\A51.EXE‘
  • 【智慧工地源码】智慧工地云平台系统,涵盖安全、质量、环境、人员和设备五大管理模块,实现实时监控、智能预警和数据分析。
  • PYTHON让繁琐的工作自动化-猜数字游戏
  • 从数据汇总到高级分析,SQL 查询进阶实战(下篇)—— 分组、子查询与窗口函数全攻略
  • 车e估牵头正式启动乘用车金融价值评估师编制
  • CoRL 2025|隐空间扩散世界模型LaDi-WM大幅提升机器人操作策略的成功率和跨场景泛化能力
  • 从「行走」到「思考」:机器人进化之路与感知—决策链路的工程化实践
  • 第4.3节:awk正则表达式详解-特殊字符
  • Pytest测试框架基础及进阶
  • 前端css学习笔记7:各种居中布局空白问题
  • Jenkins全链路教程——Jenkins调用Maven构建项目
  • IoT/透过oc_lwm2m和at源码,分析NB-IoT通信模组和主板MCU之间的通信过程
  • 【Jenkins】03 - 自动构建和docker构建
  • 【opencv-Python学习笔记(7):图像平滑处理】
  • 删除并获得点数
  • label studio标注时序数据
  • 力扣热题100------19.删除链表的倒数第N个结点