第四篇:从点击到显示——App 启动与 Activity 生命周期全追踪

当你手指轻触桌面上的微信图标,屏幕瞬间亮起熟悉的界面。这看似简单的"点击",背后却是一场跨越多个进程、涉及数十次 Binder 通信的精密接力赛。

AMS(ActivityManagerService) 是总指挥,Zygote 是兵工厂,Binder 是传令兵,而 ActivityThread 则是前线的执行者。

本篇我们将像侦探一样,追踪从"点击图标"到 onResume() 被调用的完整链路,揭开 Android 应用启动的神秘面纱。


第一步:Launcher 发起冲锋 ------ 请求启动

一切始于 Launcher (桌面应用)。当你点击图标时,Launcher 并不知道微信的具体代码在哪里,它只知道一个 Intent

代码位置packages/apps/Launcher3/src/com/android/launcher3/Launcher.java

ini 复制代码
// Launcher 中的点击事件处理
public void onClick(View v) {
    Object tag = v.getTag();
    if (tag instanceof ShortcutInfo) {
        ShortcutInfo info = (ShortcutInfo) tag;
        Intent intent = info.intent;
        
        // 【关键】启动 Activity
        // 这里最终会调用 startActivitySafely -> startActivity
        startActivity(intent); 
    }
}

底层动作
startActivity 最终通过 Binder 调用 AMSstartActivityAsUser 方法。

此时状态:Launcher 进程挂起(等待 AMS 裁决),控制权移交系统服务。


第二步:AMS 的决策 ------ 寻找或创建进程

AMS 收到请求后,开始进行复杂的逻辑判断。

代码位置frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

AMS 决策流程图

关键逻辑伪代码

scss 复制代码
// AMS 内部简化逻辑
final int startActivityAsUser(...) {
    // 1. 权限检查 (SELinux, Manifest 权限)
    enforceNotIsolatedCaller("startActivity");
    
    // 2. 解析 ResolveInfo (找到具体的 Activity 类名)
    ResolveInfo rInfo = mAppIntents.resolveIntent(intent, ...);
    
    // 3. 获取或创建进程记录 (ProcessRecord)
    ProcessRecord targetApp = getProcessRecordLocked(targetPackage, targetUid);
    
    if (targetApp == null || targetApp.thread == null) {
        // 【核心】进程不存在,需要启动新进程
        startProcessLocked(targetPackage, ...); 
    } else {
        // 进程已存在,直接调度
        targetApp.thread.scheduleLaunchActivity(...);
    }
    
    return START_SUCCESS;
}

第三步:Zygote 再次登场 ------ 孵化新进程

如果目标 App 未运行,AMS 会通过 Socket 向 Zygote 发送指令。

通信协议

AMS 写入 Socket 的数据包包含:uid, gid, gids, debugFlags, runtimeFlags, mountExternal, seInfo, niceName, fdsToClose, fdsToIgnore, isTopApp, disabledCompatChanges, pkgDataInfoMap, whitelistedDataInfoMap, bindMountAppDataDirs, bindMountAppStorageDirs, args[] (其中包含 --activity-thread 等参数)。

Zygote 响应

Zygote 收到后,执行 forkAndSpecialize,生成新进程。新进程入口是 ActivityThread.main


第四步:App 进程的自我修养 ------ ActivityThread.main

新进程诞生后,它首先是一个普通的 Java 进程,还没有"Application"的概念。它需要自己初始化。

代码位置frameworks/base/core/java/android/app/ActivityThread.java

arduino 复制代码
// 文件:frameworks/base/core/java/android/app/ActivityThread.java
public static void main(String[] args) {
    // 1. 初始化主线程 Looper
    Looper.prepareMainLooper();

    // 2. 实例化 ActivityThread (当前进程的代表)
    ActivityThread thread = new ActivityThread();
    
    // 3. 【关键】绑定 Application
    // 调用 AMS 的 attachApplication,注册自己
    thread.attach(false, initialPid); 

    // 4. 进入消息循环
    Looper.loop();
}

attach 方法的秘密

java 复制代码
private void attach(boolean system, long startSeq) {
    // 获取 AMS 的代理对象 (IActivityManager)
    final IActivityManager mgr = ActivityManager.getService();
    
    try {
        // 告诉 AMS:"我启动了,这是我的 Binder 代理"
        // AMS 会保存这个代理,以便后续直接回调我们
        mgr.attachApplication(mAppThread, startSeq); 
    } catch (RemoteException ex) {
        throw ex.rethrowFromSystemServer();
    }
    
    // 等待 AMS 下发指令 (如 bindApplication, launchActivity)
    // 这些指令会通过 Binder 异步到达,放入 Handler 队列
}

Binder 魔法 :此时,AMS 手中持有了新进程的 IApplicationThread 代理。以后 AMS 想启动 Activity,只需调用 appThread.scheduleLaunchActivity(),请求就会瞬间发送到新进程的 Binder 线程池,再转发给主线程 Handler。


第五步:生命周期的大合唱 ------ 从 onCreate 到 onResume

AMS 确认进程就绪后,开始编排 Activity 的生命周期。这是一次典型的 RPC(远程过程调用) 舞蹈。

Activity 启动全流程

核心代码模拟 (ActivityThread.handleLaunchActivity)

scss 复制代码
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    // 1. 加载类
    Class<?> clazz = r.loadClass(mClassLoader);
    
    // 2. 实例化 Activity
    Activity activity = (Activity) clazz.newInstance();
    
    // 3. 创建 Context (包裹 Activity)
    ContextImpl appContext = createBaseContextForActivity(r, activity);
    
    // 4. 调用生命周期
    Instrumentation inst = mInstrumentation;
    
    // --- 用户代码执行点 ---
    activity.attach(appContext, ...);
    inst.callActivityOnCreate(activity, r.state); // 调用 onCreate
    activity.performStart();                      // 调用 onStart
    inst.callActivityOnResume(activity);          // 调用 onResume
    // ----------------------
    
    return activity;
}

关键点 :所有的生命周期回调(onCreate, onStart, onResume)都是由 Instrumentation 类辅助调用的。这也是为什么我们可以用测试框架(如 Espresso)拦截这些回调的原因。


🔹 第六步:窗口绘制 ------ 终于看到了界面

onResume 返回后,Activity 认为自己是"可见"的,但屏幕上可能还是黑的。真正的绘制由 WindowManagerService (WMS)SurfaceFlinger 完成。

  1. Activity 创建 PhoneWindow,设置 ContentView
  2. ViewRootImpl 请求 WMS 添加窗口 (addToDisplay)。
  3. WMS 分配一个 Surface (图形缓冲区)。
  4. App 进程 在 Surface 上绘制 UI (Canvas/OpenGL)。
  5. SurfaceFlinger 合成所有图层,输出到屏幕。

这个过程是异步的,通常在 onResume 之后的几帧内完成。


本篇小结

阶段 关键角色 核心动作 通信方式
发起 Launcher 构建 Intent,调用 startActivity Binder (to AMS)
决策 AMS 检查进程,决定 Fork 或复用 内存/锁
孵化 Zygote Fork 新进程,设置 UID/GID Socket (from AMS)
绑定 ActivityThread 调用 attach,注册到 AMS Binder (to AMS)
调度 AMS 发送 scheduleLaunchActivity Binder (to App)
执行 ActivityThread 反射创建 Activity,调用生命周期 本地调用
回调 ActivityThread 通知 AMS "Resumed" Binder (to AMS)

技术洞察

  • 双向 Binder:AMS 持有 App 的代理(用于下发指令),App 持有 AMS 的代理(用于上报状态)。
  • Handler 机制:所有跨进程的生命周期回调,最终都变成了主线程 MessageQueue 中的一条消息,保证了串行执行。
  • Instrumentation:它是 Hook 生命周期的关键入口,也是单元测试的基石。

下篇预告

App 启动了,界面显示了。但如果你快速滑动列表,或者打开相机,系统如何保证不卡顿?

  • Choreographer 是如何同步 VSync 信号的?
  • View 的测量、布局、绘制 三部曲究竟发生了什么?
  • GPU 是如何介入渲染流程的?

下篇我们将深入 UI 渲染管线,揭秘 Android 流畅度背后的"帧"的秘密。
敬请期待:《60FPS 的秘密:UI 渲染管线与 Choreographer 的舞蹈》

相关推荐
huwuhang8 小时前
Winkawaks街机游戏模拟器整合ROM版 1.65 汉化修正完整版 2026.03.30
android·游戏·游戏机
yitian_hm8 小时前
MySQL主从复制与读写分离实战指南
android·mysql·adb
NEGl DRYN8 小时前
Plugin ‘mysql_native_password‘ is not loaded`
android·数据库·mysql
Derrick__19 小时前
Android混淆和加密技术
android·jvm·python
sunwenjian8869 小时前
MySQL加减间隔时间函数DATE_ADD和DATE_SUB的详解
android·数据库·mysql
ictI CABL10 小时前
MySQL Workbench菜单汉化为中文
android·数据库·mysql
放学以后Nicetry11 小时前
Android SELinux 指南:从基本概念到实战修复
android
CCIE-Yasuo11 小时前
《永恒战士2-无双战神》无限金币版(提供apk下载)安卓Android逆向记录学习-Deepseek-AI辅助
android·java·学习·游戏
jzlhll12313 小时前
kotlin flow去重distinctUntilChanged vs distinctUntilChangedBy
android·开发语言·kotlin
渡我白衣13 小时前
【MySQL基础】(3):MySQL库与表的操作
android·数据库·人工智能·深度学习·神经网络·mysql·adb