Skip to content
阅读进度

为什么不能在子线程中直接更新 UI?Handler 是如何解决这个问题的? ​

返回 Java 与并发 目录

标准回答 ​

大多数 View 状态由主线程统一管理,避免多个线程同时改同一界面。Handler 可以把结果送回这个线程。

  • 常规 Activity 界面属于主线程,状态和绘制应遵守单线程约束。
  • 后台线程负责 IO 或计算,结果通过主线程 Handler 应用到 View。
  • 绑定 Looper.getMainLooper,避免误绑定当前子线程。

通俗例子 ​

后台线程下载完成后,向主线程 Handler post 一个更新文字的任务。下载在后台,setText 在主线程执行。

深入解释 ​

**为什么统一到主线程:**View 的内部状态与测量、布局、绘制会一起变化,多线程同时修改容易互相覆盖或读到不一致状态。Android 的常规界面操作因此由主线程统一处理。

**一个完整的做法:**后台完成网络或计算后,把纯结果传回主线程;主线程先确认页面仍有效,再更新 View。不要把整个下载过程一起 post 回去。

示例代码 ​

java
Handler main = new Handler(Looper.getMainLooper());
executor.execute(() -> {
    Result result = loadData();
    main.post(() -> render(result));
});

易混淆点 ​

不是所有越线程访问都会立刻报错;偶尔没崩也不能证明线程安全。

参考资料 ​

内容来源 ​

用完整回答理解机制,用真实证据解释项目。