一句话总结
主线程的消息循环就像快递站的分拣系统,从Zygote“克隆”出来的App进程,一出生就装好了传送带(Looper)和分拣机(Handler),保证所有快递(消息)有序处理。
一、主线程的诞生:进程的复制与入口的执行
- Zygote 进程:Android 系统在启动时,会创建一个特殊的“模板进程”——Zygote。这个进程预先加载了所有的 Android 核心库和常用资源,并启动了一个 JVM。
- App 进程的创建:当用户启动一个应用时,系统会通过
fork系统调用,从 Zygote 进程复制出一个新的 App 进程。这个过程采用了写时复制(Copy-on-Write) 技术,使得 App 进程可以共享 Zygote 的内存,从而极大地加快了应用的启动速度。 - 主线程的起点:新创建的 App 进程会立即执行其入口函数
ActivityThread.main()。这个方法是 App 主线程的起点,它负责初始化主线程的消息循环系统。
二、主线程的核心装备:消息循环系统
主线程之所以能够处理所有 UI 和事件任务,是因为它装备了一个精密的消息循环系统。
Looper:主线程的“循环器”。它会通过一个永不停止的Looper.loop()方法,不断地从消息队列中取出消息并分发给Handler。MessageQueue:主线程的“消息队列”。它是一个有序的任务列表,所有的 UI 更新和事件都排队在此。Handler:主线程的“传令兵”。它负责向MessageQueue中发送和分发消息。主线程可以有多个Handler,但只有一个Looper和一个MessageQueue。
三、主线程的职责与系统调度
主线程是一个单线程模型,它需要处理所有与 UI 相关的任务。
- UI 事件:处理用户的点击、滑动等输入事件。
- 系统回调:接收来自系统的各种回调,如
Activity的onCreate、onResume等生命周期方法。 - 跨进程通信:通过 Binder 机制,主线程可以接收来自系统服务(如
ActivityManagerService)的消息。
-
调度流程:
AMS向 App 进程发送一个 Binder 消息(如启动一个Activity)。- 消息到达 App 进程的 Binder 线程。
- Binder 线程将这个 Binder 消息封装成一个
Message,并使用Handler发送到主线程的MessageQueue。 Looper从队列中取出这个Message,并调用Handler的handleMessage方法,最终执行Activity.onCreate()等回调。
四、ANR:主线程的致命弱点
由于主线程是一个单线程,任何阻塞它的耗时操作都会导致应用无响应。
-
超时机制:如果主线程在一定时间内没有响应用户输入或系统事件,系统就会触发 ANR(Application Not Responding)错误,并弹出对话框。
-
典型场景:
- 输入事件:主线程在 5 秒内没有处理完一个输入事件(如点击)。
- 广播:主线程在 10 秒内没有处理完一个广播。
-
如何避免:将所有耗时操作(如网络请求、文件 I/O、数据库查询)转移到子线程中执行,从而确保主线程始终保持流畅。