第1章:启动阶段拆解——应用进程创建、Application初始化、Activity生命周期与关键时间节点

1.1 启动流程总览

应用启动并非单一瞬间动作,而是操作系统与Android框架协作完成的串行过程。整个过程可拆解为四个子阶段:

  • 进程创建:Zygote进程收到AMS请求,fork出新进程并运行ActivityThread。
  • Application初始化:创建Application对象,调用attachBaseContext()和onCreate()。
  • Activity生命周期启动:创建目标Activity,走完onCreate/onStart/onResume。
  • 首帧绘制:View树完成测量、布局、绘制,并送出第一帧。

开发者可直接干预的监控时间节点有三个:processStart、applicationOnCreate、activityOnResume。其余系统内核阶段只能通过trace和日志间接观测。

1.2 关键阶段与时间节点对照

子阶段 关键动作 时间节点/API 监控数据来源
进程创建 Zygote fork → ActivityThread.main() processStart Logcat (Zygote)
Application初始化 attachBaseContext → onCreate applicationOnCreate 手动埋点 + API
Activity生命周期 onCreate → onStart → onResume activityOnResume ReportFullyDrawn
首帧绘制 ViewRootImpl.performTraversals frameCallback Choreographer

1.3 启动流程SVG框架图

下图展示了从用户点击图标到首帧显示的完整启动阶段,包含核心节点与系统边界:

应用启动阶段拆解流程图 启动阶段拆解流程图(用户点击 → 首帧显示) 用户点击桌面图标 AMS:解析Intent → 准备启动进程 (系统进程 / 非应用进程) Zygote:fork() 创建新进程 (线程池复制 + ClassLoader 预热) ⏱️ processStart ActivityThread.main() (主线程Lopper开始轮询) 阶段二:Application 初始化(应用进程内部,所有操作在主线程) attachBaseContext() Application.onCreate() ContentProvider.onCreate() ⏱️ applicationOnCreate 阶段三:目标 Activity 生命周期 + 首帧 onCreate() onStart() onResume() 首帧 ⏱️ activityOnResume

1.4 进程创建阶段详解

用户点击桌面图标后,Launcher通过Binder向ActivityManagerService(AMS)发送启动Intent。AMS首先判断目标进程是否已存在:

  • 若存在且已绑定,直接复用进程并走Application生命周期。
  • 若不存在,AMS通过Socket向Zygote进程发送startProcess请求。

Zygote收到请求后执行ZygoteConnection.processOneCommand(),完成以下工作:

  1. fork()创建子进程,进程ID为新值。
  2. 子进程继承Zygote的预加载资源(ClassLoader、系统Framework类、共享库等)。
  3. 子进程调用ActivityThread.main()进入应用主循环。
  4. 主线程创建ActivityThread实例并绑定ApplicationThread(用于与AMS通信的Binder)。

监控指标:从AMS发送请求到ActivityThread.main()开始执行的时间差。此值通常在200~800ms(取决于设备性能和Zygote堆大小)。无法用Android SDK API直接获取,需通过adb logcat -b all | grep “Zygote”或systrace观测。

1.5 Application初始化阶段详解

当ActivityThread准备就绪后,AMS通过Binder向应用进程发送bindApplication消息。此时进程内部执行顺序固化:

  1. 创建ContextImpl并调用Application.attachBaseContext()。
  2. 执行Application.onCreate()——这是开发者常用的初始化入口。
  3. 创建并初始化所有注册的ContentProvider,依次调用其onCreate()。

在onCreate()中,开发者常做以下耗时代码操作,需重点监控:

建议监控点:在 Application.onCreate() 首行记录时间,末行记录差值,规避后续 Activity 启动被阻塞。
// 示例:监控 Application.onCreate 耗时
class MyApp : Application() {
    override fun onCreate() {
        val start = System.currentTimeMillis()
        super.onCreate()
        // … SDK 初始化等代码 …
        val elapsed = System.currentTimeMillis() - start
        Log.d("AppStartup", "Application.onCreate 耗时: $elapsed ms")
    }
}

1.6 Activity生命周期阶段详解

Application初始化完成后,AMS向ActivityThread发送launchActivity事务。目标Activity依次执行:

回调方法 主要工作 常见耗时场景 监控手段
onCreate() setContentView、inflate布局、初始化View / Fragment / Adapter 复杂XML解析、大量View创建、数据预加载 手动埋点
onStart() 准备界面可见前的轻量工作(状态恢复、注册观察者等) 耗时短,通常<5ms 手动埋点
onResume() 确保前台运行、开始动画/视频/传感器 启动动画、VP播放、网络请求 ReportFullyDrawn

首帧绘制发生在onResume()之后。系统通过Choreographer注册回调,在下一帧VSYNC信号到达时执行performTraversals()完成ViewRootImpl的测量、布局、绘制。首帧时间可通过Activity.reportFullyDrawn()(API 24+)或Choreographer的帧回调精确捕获。

性能原则:onCreate() 和 onStart() 中避免执行任何I/O、网络、复杂计算,只做UI和轻量状态恢复。所有耗时初始化推迟到 onResume() 后的 IdleHandler 或协程中执行。

1.7 关键时间节点定义与取值

时间节点 定义 建议取值API
processStart Zygote完成fork并开始执行ActivityThread.main() systrace/logcat
applicationOnCreate Application.onCreate() 执行结束 System.currentTimeMillis()
activityOnResume 目标Activity.onResume() 执行结束 手动埋点 + reportFullyDrawn
firstFrameDrawn ViewRootImpl完成首帧绘制并提交到SurfaceFlinger Choreographer.postFrameCallback
常见错误:不要在 Application.onCreate() 或 Activity.onCreate() 中使用 ContentResolver.query() 或 SharedPreferences.getString() 等I/O操作,它们会触发磁盘读或ContentProvider创建,直接增加启动耗时 50~300ms。例如:
// 错误示例 → 阻塞启动
class MyApp : Application() {
    override fun onCreate() {
        super.onCreate()
        val name = getSharedPreferences("pref", 0).getString("key", "")  // 磁盘I/O!
        val cursor = contentResolver.query(Uri.parse("…"), null, null, null)  // 跨进程!
    }
}

1.8 本章小结

应用启动耗时可划分为4个子阶段,其中开发者能直接干预和监控的是Application初始化与Activity生命周期。定义清晰的processStart、applicationOnCreate、activityOnResume、firstFrameDrawn四个时间节点,是后续启动优化的数据基础。本章的拆解方法将贯穿整个课程,每阶段耗时优化都会回溯到这里的定义和边界。