Android 主线程一定是 UI 线程吗?
背景知识:Android 线程模型基础
在 Android 开发中,线程管理是保证应用流畅性和稳定性的核心。官方文档中曾提到:"Main thread is also sometimes called the UI thread."(主线程有时也被称为 UI 线程)。然而,这句话并非在所有场景下都绝对成立。理解主线程(Main Thread)与 UI 线程(UI Thread)的区别,对于深入掌握 Android 框架机制至关重要。
在线程注解的章节中,Google 给出了更严谨的定义:构建工具会将 @MainThread 和 @UiThread 注解视为可互换,允许从 @MainThread 方法调用 @UiThread 方法,反之亦然。但是,如果不同线程上具有多个视图的系统应用程序的界面线程可能会与主线程不同。因此,建议开发者使用 @UiThread 为与应用的视图层次结构关联的方法添加注解,并使用 @MainThread 仅为与应用生命周期关联的方法添加注解。
核心源码深入:ActivityThread 初始化流程
为了探究这一结论,我们从 Activity#runOnUiThread(Runnable) 入手,查看系统源码。
public final void runOnUiThread(Runnable action) {
if (Thread.currentThread() != mUiThread) {
mHandler.post(action);
} else {
action.run();
}
}
这段代码逻辑非常清晰:它判断当前线程是否等于 mUiThread。如果不是,则通过 Handler 发送消息到 UI 线程处理;如果是,则直接执行。这里的焦点在于 mUiThread 属性的初始化位置。
在 Activity.java 的 attach 方法中,我们可以找到 mUiThread 的赋值过程:
// in Activity.java
@UnsupportedAppUsage
final void attach(Context context, ActivityThread aThread,
Instrumentation instr, IBinder token, int ident,
Application application, Intent intent, ActivityInfo info,
CharSequence title, Activity parent, String id,
NonConfigurationInstances lastNonConfigurationInstances,
Configuration config, String referrer, IVoiceInteractor voiceInteractor,
Window window, ActivityConfigCallback activityConfigCallback, IBinder assistToken) {
attachBaseContext(context);
// ...
mUiThread = Thread.currentThread();
mMainThread = aThread;
// ...
}
这里有两个关键属性:
- :直接被赋值为当前线程(即执行 attach 方法的线程)。

