一句话总结
startActivity() 调用的背后,是一个由应用进程、system_server 和 Zygote 共同协作的复杂跨进程调度系统。
一、发起启动:应用进程的代理人
startActivity() 调用的起点是应用进程,它通过 Instrumentation 作为代理,向系统发起启动请求。当开发者调用 Activity.startActivity() 时,这个请求被封装成一个 Intent。Instrumentation 作为核心中间件,负责获取 ActivityManagerService(AMS) 在本地的 Binder 代理(IActivityTaskManager) ,并利用它发起一次跨进程调用。这个过程就像是应用进程通过一条专线电话,向系统的总调度中心(AMS)汇报:“我要启动一个 Activity!”
二、AMS:总调度中心的决策与任务分发
运行在 system_server 进程中的 AMS,是整个 Activity 启动流程的“总指挥”。它接收到请求后,会扮演以下几个关键角色:
-
安全与合法性审查: AMS 会首先校验调用者的权限,并检查
Intent中包含的信息是否合法。 -
进程管理: 这是 AMS 的核心职能之一。它会检查目标
Activity所在的进程是否已经存在。- 如果进程不存在,AMS 会通过一个特殊的
Socket通道,向Zygote进程发送指令。Zygote随即通过fork()机制,快速复制出一个新的应用进程。这里使用Socket的原因在于,Zygote主要负责进程的创建,而非复杂的方法调用,Socket这种简单的通信机制足以完成“唤醒”任务。 - 如果进程已存在,AMS 会直接准备下一步的启动指令。
- 如果进程不存在,AMS 会通过一个特殊的
-
创建
ActivityRecord: 为了管理Activity的生命周期和状态,AMS 会为即将创建的Activity实例在内存中生成一个“档案卡”——ActivityRecord。这个对象包含了Intent、所在的任务栈等所有元数据,并最终被添加到任务栈(ActivityTask)中。这确保了Activity的状态在跨进程的生命周期中得到统一管理。
三、逆向通信:AMS 回调应用进程
在 AMS 完成所有准备工作后,它需要将控制权交还给应用进程,告知其可以创建 Activity 实例了。这个过程并非简单的信号,而是一次完整的 Binder 逆向调用。
ApplicationThread的作用: 应用进程在启动之初,就在ActivityThread中注册了一个特殊的 Binder 实体——IApplicationThread。AMS 就像是拥有这个“逆向电话号码”一样,可以随时发起对应用进程的调用。- 发起回调: AMS 通过
IApplicationThread的 Binder 代理,调用scheduleLaunchActivity()方法。这次调用将ActivityRecord等关键信息从system_server进程传递回应用进程。
四、Activity 的诞生:应用进程的线程调度
应用进程接收到 AMS 的回调后,ActivityThread 将迎来最繁忙的时刻。
Handler消息机制: 接收到scheduleLaunchActivity()调用后,应用进程的主线程(ActivityThread)并不会立即创建Activity。它会通过Looper和Handler机制,将一个LAUNCH_ACTIVITY消息添加到主线程的消息队列中。这种设计确保了 UI 操作总是在主线程上按序执行,避免了并发问题。- 实例创建与生命周期: 当主线程的
Handler处理到这条消息时,它会通过反射创建Activity实例,并依次调用onCreate()、onStart()、onResume()等生命周期方法。 - UI 绘制:
Activity实例创建并完成生命周期后,它的根视图(DecorView)会被添加到WindowManager,最终通过SurfaceFlinger服务,呈现在用户的屏幕上。
希望这些建议能帮助你把文章提升到一个新的水平。你对 startActivity() 的核心流程还有哪些好奇的地方?例如,不同启动模式(launchMode)会如何影响任务栈的调度?