分析startActivity启动过程

138 阅读5分钟

本文是对 Android 中startActivity启动流程的深度解析,基于 Android 6.0 源码,详细梳理了从点击启动到 Activity 生命周期回调的完整过程。以下用通俗语言和结构化逻辑描述核心内容:

一、启动流程总览

startActivity的本质是跨进程通信(IPC)系统服务协同工作的过程,主要涉及三类角色:

  1. 调用者进程(如 Launcher):发起启动请求。

  2. 系统服务进程(system_server) :通过ActivityManagerService(AMS)管理 Activity 的生命周期和任务栈。

  3. 目标进程:创建并显示目标 Activity。

核心步骤

  1. 调用者进程通过 Binder 向 AMS 发送启动请求
  2. AMS 检查权限、解析目标 Activity 信息,决定是否创建新任务栈或复用现有栈。
  3. 目标进程不存在时,通过 Zygote fork 新进程;存在时直接通知目标进程启动 Activity。
  4. 目标进程通过 Handler 机制回调 Activity 生命周期方法(如onCreate)。

二、关键流程详解

1. 应用层发起请求(调用者进程)

当在 Activity 中调用startActivity(intent)时,实际会经过以下步骤:

  • Activity.startActivityForResult
    调用Instrumentation.execStartActivity,该方法通过ActivityManagerNative.getDefault()获取ActivityManagerProxy(AMP)—— 这是 AMS 的Binder 客户端代理

  • AMP 通过 Binder 发送请求到 AMS
    通过transact方法跨进程调用 AMS 的startActivity方法,传递 Intent、调用者包名等参数。

通俗比喻
调用者进程像 “客户”,AMS 像 “服务台”,Binder 通信就是 “客户” 通过 “电话” 向 “服务台” 提交请求。

2. 系统服务层处理请求(system_server 进程)

AMS 是 Android 系统的核心服务,负责管理所有 Activity 的生命周期和任务栈。以下是关键环节:

2.1 解析目标 Activity 信息
  • ActivityStackSupervisor(ASS).resolveActivity
    通过PackageManagerService(PMS)查询系统中匹配 Intent 的 Activity 信息(如ActivityInfo)。若存在多个匹配项,会弹出选择对话框(如分享功能的应用选择)。
  • 权限检查
    检查调用者是否有权限启动目标 Activity,如声明了android:permission属性的 Activity 需验证权限。
2.2 任务栈(Task)管理
  • 任务栈的作用
    管理 Activity 的堆叠顺序,一个任务栈可包含多个属于同一应用或不同应用的 Activity。

  • 启动模式(Launch Mode)的影响

    • standard(默认) :每次启动都创建新实例,放入当前任务栈。
    • singleTop:若栈顶已是目标 Activity,直接复用(不创建新实例)。
    • singleTask:若栈中存在目标 Activity,清除其上方的所有 Activity,使其成为栈顶。
    • singleInstance:创建独立任务栈,该 Activity 独占一个栈。
  • Flags 的作用
    例如FLAG_ACTIVITY_NEW_TASK会使 Activity 在新任务栈中启动(类似浏览器新建标签页)。

2.3 处理任务栈切换与暂停
  • 暂停当前 Activity
    若启动新 Activity 时,当前栈顶 Activity 未暂停(如处于RESUMED状态),AMS 会先调用schedulePauseActivity暂停它。
  • 任务栈调度
    通过ActivityStack管理栈内 Activity 的顺序,确保前台 Activity 始终可见。若目标 Activity 属于后台任务栈,会将其移至前台(类似切换浏览器标签页)。
2.4 启动目标进程
  • 进程存在检查
    通过ProcessRecord判断目标 Activity 所属进程是否存在。若不存在,调用AMS.startProcessLocked通过 Zygote 创建新进程。
  • Zygote 的作用
    作为 Android 进程的 “孵化器”,Zygote 预加载系统资源,fork 出的新进程可快速启动(类似模板复制)。

3. 目标进程初始化 Activity(目标进程)

当目标进程创建或唤醒后,通过以下步骤启动 Activity:

  • ApplicationThread.scheduleLaunchActivity
    AMS 通过ApplicationThreadProxy(ATP)(目标进程的 Binder 代理)调用目标进程的scheduleLaunchActivity,传递 Activity 信息。

  • Handler 消息机制
    目标进程的主线程(ActivityThread)通过 Handler 接收H.LAUNCH_ACTIVITY消息,触发handleLaunchActivity方法。

  • 创建 Activity 实例
    通过反射创建 Activity 对象,调用attach方法关联上下文(Context),并依次调用生命周期方法:

    java

    onCreate() → onStart() → onResume()
    

    至此,Activity 界面渲染完成,用户可见。

三、核心概念与常见问题

1. 任务栈与 ActivityRecord

  • ActivityRecord:代表一个 Activity 实例的状态,包含组件信息、任务栈归属等。
  • 任务栈的唯一性:每个 ActivityRecord 必须属于一个任务栈(TaskRecord),任务栈通过ActivityStack管理,确保同一时刻只有一个栈处于前台。

2. 跨进程通信(IPC)的关键组件

  • Binder:Android 的核心 IPC 机制,用于进程间数据传输。

    • 客户端:调用者进程的ActivityManagerProxy(AMP)
    • 服务端:system_server 进程的ActivityManagerService(AMS)
  • Handler:目标进程通过 Handler 将 IPC 回调切换到主线程,保证 UI 操作的线程安全。

3. 常见异常与处理

  • START_INTENT_NOT_RESOLVED:Intent 无法匹配到任何 Activity(如组件名错误)。
  • START_PERMISSION_DENIED:调用者缺少启动目标 Activity 的权限。
  • 任务栈混乱:错误使用启动模式或 Flags 导致 Activity 堆叠异常(如 singleTask 未配合FLAG_ACTIVITY_CLEAR_TOP)。

四、总结:启动流程时序图

plaintext

调用者进程(如Launcher)                          system_server进程                          目标进程
┌───────────────────────┐                      ┌───────────────────────┐                  ┌───────────────────────┐
│ startActivity()       │────── Binder ───────►│ AMS.startActivity()   │                  │                       │
│                       │                      │                       │←───── 创建进程 ───│ Zygote fork          │
│                       │                      │ ASS.resolveActivity() │                  │                       │
│                       │                      │ ASS.startActivityLocked()│                  │                       │
│                       │                      │                       │───── Binder ─────►│ ApplicationThread    │
│                       │                      │                       │                  │ scheduleLaunchActivity() │
│                       │                      │                       │←──── 消息机制 ────│ Handler(H.LAUNCH_ACTIVITY) │
└───────────────────────┘                      └───────────────────────┘                  │                       │
                                                              └───────────────────────┘
                                                                   ▼
                                                             Activity.onCreate()

五、开发建议

  1. 合理使用启动模式:根据业务需求选择Launch Mode(如登录页用 singleTask 避免重复实例)。

  2. 避免内存泄漏:非必要情况下,避免在 Activity 中持有跨进程的长生命周期对象(如 AMS 的引用)。

  3. 权限与兼容性:动态检查权限(如 Android 6.0 + 的运行时权限),确保不同设备和系统版本的兼容性。

通过理解startActivity的底层流程,开发者可更精准地优化应用启动性能、解决任务栈异常等问题,提升用户体验。