深入理解 Activity 启动流程:从点击到界面展示,中间到底发生了什么?

4 阅读4分钟

一、引言:为什么必须搞懂 Activity 启动流程?

很多 Android 开发者在日常开发中都会写:

startActivity(Intent(this, DetailActivity::class.java))

看起来简单,但你有没有遇到过这些问题:

  • 为什么 冷启动慢
  • 为什么有时候会 白屏/黑屏
  • onCreate() 到底什么时候被调用?
  • 多进程/多任务栈下,为什么行为“奇怪”?
  • 启动优化该从哪下手?

👉 本质上,这些问题都指向同一个核心:Activity 启动流程

如果你不了解这条链路,就只能“猜”;
但一旦理解了,就能做到:

  • 精准定位启动性能瓶颈
  • 正确设计页面跳转结构
  • 避免生命周期误用
  • 做出真正有效的优化

二、背景知识:你需要知道的几个关键角色

在深入之前,我们先建立一个“地图”:

1. 进程划分(非常关键)

  • App 进程

    • 执行你的代码
    • 包含 Activity、View、业务逻辑
  • System Server 进程

    • 系统核心服务
    • 包含 AMS(ActivityManagerService)

👉 一句话总结:

Activity 启动 = App 进程请求 → System Server 决策 → 再回调 App


2. 核心组件

组件作用
Activity页面
AMS调度 Activity
ATMS专门管理 Activity(Android 10+)
Instrumentation启动 Activity 的“执行器”
ActivityThreadApp 主线程的入口

3. 启动方式

  • 显式启动
  • 隐式启动
  • 冷启动 / 热启动 / 温启动

👉 后面我们重点讲 冷启动路径(最复杂)


三、核心原理解析:一张图看懂启动流程

我们先用一句话总结:

Activity 启动 = 一次跨进程调用 + 一次进程创建 + 一次生命周期分发

拆开来看是这样:

App.startActivity()
        ↓
AMS(系统进程)
        ↓
(如果进程不存在)Zygote fork 新进程
        ↓
ActivityThread(主线程)
        ↓
Instrumentation 创建 Activity
        ↓
onCreate → onStart → onResume

四、源码级流程分析(重点)

我们从一行代码开始:

startActivity(Intent(this, DetailActivity::class.java))

Step 1:Activity.startActivity()

public void startActivity(Intent intent) {
    Instrumentation.execStartActivity(...)
}

👉 关键点:

  • Activity 自己并不启动 Activity
  • 它把任务交给了 Instrumentation

Step 2:Instrumentation.execStartActivity()

ActivityTaskManager.getService().startActivity(...)

👉 这里发生了什么?

  • 通过 Binder 调用系统服务
  • 跨进程进入 System Server

Step 3:进入 AMS / ATMS(系统进程)

核心逻辑:

ActivityStarter.execute()

它会做几件关键事情:

① 解析 Intent

  • 找到目标 Activity
  • 检查权限

② 处理任务栈(Task)

  • 是否复用已有 Activity?
  • 是否创建新 Task?

③ 判断进程是否存在

👉 关键分支:

情况行为
进程已存在直接调度
进程不存在创建新进程

Step 4:如果进程不存在 → 创建进程(冷启动关键)

ZygoteProcess.start(...)

👉 本质:

通过 Zygote fork 一个新进程

新进程启动后会执行:

ActivityThread.main()

Step 5:ActivityThread 处理启动

系统会通过 Binder 回调:

scheduleLaunchActivity()

然后在主线程执行:

handleLaunchActivity()

Step 6:创建 Activity 实例

val activity = mInstrumentation.newActivity(...)

👉 本质:

反射创建 Activity 对象


Step 7:生命周期回调

activity.performCreate()
activity.performStart()
activity.performResume()

最终调用:

onCreate()
onStart()
onResume()

⭐ 到这里,页面才真正显示出来


五、实战示例:模拟 Activity 启动过程

我们写一个简单 Demo 来观察流程:

示例代码

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        log("onCreate")
        
        setContentView(R.layout.activity_main)

        findViewById<Button>(R.id.btn).setOnClickListener {
            startActivity(Intent(this, DetailActivity::class.java))
        }
    }

    override fun onStart() {
        super.onStart()
        log("onStart")
    }

    override fun onResume() {
        super.onResume()
        log("onResume")
    }

    private fun log(msg: String) {
        Log.d("MainActivity", msg)
    }
}

观察点

点击按钮后,你会看到:

MainActivity onPause
DetailActivity onCreate
DetailActivity onStart
DetailActivity onResume
MainActivity onStop

👉 这说明:

新 Activity Resume 后,旧 Activity 才 Stop


六、常见误区 / 踩坑总结

❌ 误区 1:startActivity 就是直接 new Activity

👉 错!

真实过程是:

跨进程 + 系统调度 + 生命周期驱动


❌ 误区 2:onCreate 一定很快执行

👉 不一定!

如果是冷启动:

  • 进程创建(几十 ms)
  • Application 初始化
  • View inflate

👉 可能 几百毫秒甚至更慢


❌ 误区 3:页面卡顿一定是 Activity 问题

👉 实际可能是:

  • Application 太重
  • ContentProvider 初始化
  • 主线程 IO

❌ 误区 4:任务栈行为可预测

👉 如果你不理解:

  • launchMode
  • taskAffinity

👉 行为会“非常玄学”


七、性能优化 & 最佳实践(重点加分)


1. 冷启动优化核心路径

冷启动时间 =

进程创建 + Application + Activity

优化建议:

✅ 减少 Application 初始化

// ❌ 不要在 Application 做重操作
override fun onCreate() {
    initSDK() // 耗时
}

👉 改为延迟初始化:

Handler(Looper.getMainLooper()).post {
    initSDK()
}

2. 减少首屏布局复杂度

<!-- ❌ 深层嵌套 -->
LinearLayout
    LinearLayout
        RelativeLayout

👉 使用:

  • ConstraintLayout
  • ViewStub

3. 使用启动占位(避免白屏)

<style name="AppTheme" parent="Theme.MaterialComponents">
    <item name="android:windowBackground">@drawable/launch_bg</item>
</style>

4. 避免主线程阻塞

// ❌
val data = loadFromDisk()

// ✅
lifecycleScope.launch {
    val data = withContext(Dispatchers.IO) {
        loadFromDisk()
    }
}

5. Activity 启动链路优化

👉 常见问题:

  • 多层跳转(Splash → Login → Home)

👉 优化:

合并跳转,减少中间 Activity


八、总结:你真正需要记住的 5 件事


1️⃣ Activity 启动不是函数调用,而是系统调度


2️⃣ 核心链路:

App → AMS → Zygote → ActivityThread → 生命周期

3️⃣ 冷启动慢,本质是“进程创建 + 初始化”


4️⃣ 生命周期不是“回调”,而是“系统驱动”


5️⃣ 优化启动 = 优化主线程 + 减少初始化 + 控制布局复杂度


最后一句

你写的是 startActivity,但系统做的是一整套进程调度系统。

理解这件事,是从“会用 Android”走向“掌控 Android”的分水岭。