用通俗易懂的故事和关键代码片段,来理解这篇 Android 应用程序启动源码分析的精华。想象一下你点击手机桌面上的一个App图标(比如“计算器”),背后发生了一场精密的“快递接力赛”。
核心故事:一次点击引发的“快递”接力
-
你下单了!(Launcher -> startActivity)
-
你点击了计算器图标(
Launcher应用)。 -
Launcher说:“用户想用计算器!我得通知调度中心(ActivityManagerService,简称AMS)。” 它创建了一个Intent(快递单),上面写着“收件人:计算器App的主界面(MainActivity)”,并贴上了“请用新卡车运送” (FLAG_ACTIVITY_NEW_TASK) 的标签。 -
代码体现 (
Launcher.java):java Copy void startActivitySafely(Intent intent, Object tag) { intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // 贴上“新卡车”标签 try { startActivity(intent); // 发出订单 } catch ... // 处理异常 } -
这个
startActivity(intent)调用最终会通过Activity.startActivityForResult -> Instrumentation.execStartActivity。
-
-
快递员接单,联系调度中心 (Launcher -> AMS)
-
Launcher内部的快递员 (Instrumentation) 拿起电话(Binder IPC),打给AMS的前台 (ActivityManagerProxy):“嘿调度中心,有订单!用户要启动计算器App的主界面,用新卡车!” -
代码体现 (
Instrumentation.java->ActivityManagerProxy.java):java Copy // Instrumentation.execStartActivity int result = ActivityManagerNative.getDefault() // 拿到AMS的代理 .startActivity(whoThread, intent, ...); // 调用AMS代理的方法 // ActivityManagerProxy.startActivity (代理,负责打包数据跨进程发送) public int startActivity(...) throws RemoteException { Parcel data = Parcel.obtain(); // 打包数据 ... // 写入intent等信息 mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0); // Binder跨进程发送 ... // 读取结果 }
-
-
调度中心处理订单 (AMS)
-
AMS(真正的调度中心) 收到订单 (ActivityManagerService.startActivity)。 -
AMS查看订单 (Intent):“计算器App?它的主界面?用新卡车...明白了。” 它查数据库 (PackageManagerService) 确认这个App的信息 (ActivityInfo)。 -
AMS发现计算器App还没运行:“需要一辆新卡车(新进程)!” 它在内部记录本 (ActivityStack) 上创建了一个新任务 (TaskRecord) 来放这个主界面。 -
AMS对正在前台工作的Launcher说:“Launcher,用户点了别的App,你先去后面休息室待命(进入Paused状态),等会儿可能需要你回来。” -
代码体现 (
ActivityManagerService.java/ActivityStack.java):java Copy // AMS.startActivity -> ActivityStack.startActivityMayWait // ... 解析Intent,找到目标ActivityInfo ... synchronized (mService) { ... // 权限等检查 int res = startActivityLocked(...); // 核心启动逻辑 } // ActivityStack.startActivityLocked -> startActivityUncheckedLocked if (需要新Task) { r.task = new TaskRecord(...); // 创建新任务记录 newTask = true; } resumeTopActivityLocked(prev); // 尝试让最顶上的Activity(新任务)运行,这会先暂停当前Activity // 暂停Launcher (Step 10-11) if (mResumedActivity != null) { // Launcher还在前台 startPausingLocked(userLeaving, false); // 告诉Launcher暂停 }
-
-
通知前台休息 (AMS -> Launcher)
-
AMS打电话 (Binder IPC) 给Launcher内部的专属接线员 (ApplicationThread):“Launcher,请暂停你当前的工作!” -
Launcher的专属接线员 (ApplicationThread) 收到消息后,立刻写了个便签 (Message),交给Launcher的主管家 (H-Handler):“老板,调度中心让你暂停一下。” -
Launcher的主管家 (H) 看到便签后,对Launcher说:“老板,按流程执行onPause()吧。” -
Launcher执行完onPause()后,通过它的专属接线员 (ApplicationThread) 回电话给AMS:“调度中心,我已经暂停好了 (activityPaused)。” -
代码体现 (
ApplicationThread.java->ActivityThread.java->ActivityManagerProxy.java):java Copy // ApplicationThread.schedulePauseActivity (收到AMS暂停请求) public final void schedulePauseActivity(...) { queueOrSendMessage(H.PAUSE_ACTIVITY, token, ...); // 发送消息给主线程Handler } // H (Handler) 处理 PAUSE_ACTIVITY 消息 case PAUSE_ACTIVITY: handlePauseActivity(...); // ActivityThread.handlePauseActivity performPauseActivity(...); // 调用Activity.onPause() ActivityManagerNative.getDefault().activityPaused(token, state); // 通知AMS暂停完成
-
-
调度中心派出新卡车 (AMS 启动新进程)
-
AMS收到Launcher暂停完成的通知。 -
AMS说:“好了,Launcher让位了。现在该启动计算器App的新卡车了!” -
AMS呼叫车辆调配中心 (Zygote):“请派一辆新车,司机就用android.app.ActivityThread这个培训手册,车牌号(进程名)叫shy.luo.activity(计算器App的包名)。” -
代码体现 (
ActivityManagerService.java):java Copy // ActivityStack.realStartActivityLocked 之前检查进程 ProcessRecord app = mService.getProcessRecordLocked(r.processName, ...); if (app == null || app.thread == null) { // 进程不存在或没准备好 mService.startProcessLocked(r.processName, ...); // 启动新进程! return; } // AMS.startProcessLocked (核心) int pid = Process.start("android.app.ActivityThread", ...); // 请求Zygote fork新进程
-
-
新车出厂,司机报到 (新进程初始化)
-
Zygote成功分叉 (fork) 出一个新进程。 -
在这个新进程里,
android.app.ActivityThread的main()方法被调用。这是每个App进程的主心骨。 -
main()方法创建了ActivityThread实例 (mAppThread是其内部类ApplicationThread),并建立了消息循环 (Looper.loop())。 -
新进程的
ActivityThread主动打电话给AMS:“调度中心你好,我是新车shy.luo.activity的专属接线员 (ApplicationThread),我的电话号码 (IBinder) 是mAppThread,以后有事请打这个电话找我!” -
代码体现 (
ActivityThread.java):java Copy public static void main(String[] args) { ... // 初始化 ActivityThread thread = new ActivityThread(); thread.attach(false); // 重要!向AMS报到 Looper.prepareMainLooper(); // 准备消息循环 ... // 其他初始化 Looper.loop(); // 开始处理消息(无限循环) } private void attach(boolean system) { ... // 非系统应用 IActivityManager mgr = ActivityManagerNative.getDefault(); mgr.attachApplication(mAppThread); // 向AMS注册本进程的ApplicationThread }
-
-
调度中心下达送货指令 (AMS -> 新进程)
-
AMS收到新进程的报到电话 (attachApplication)。 -
AMS很高兴:“新车shy.luo.activity的接线员 (ApplicationThread) 上线了!正好有任务给他。” -
AMS立刻通过Binder IPC打电话给新进程的专属接线员 (ApplicationThread):“嘿,新车司机!你的第一个任务:启动你车上的shy.luo.activity.MainActivity这个货(Activity)!” -
代码体现 (
ActivityManagerService.java->ApplicationThreadProxy.java):java Copy // AMS.attachApplicationLocked (收到新进程报到) ... // 找到对应的ProcessRecord app app.thread = thread; // 保存新进程的ApplicationThread ... // 检查 if (有Activity等待在此进程启动) { // 就是我们的MainActivity if (mMainStack.realStartActivityLocked(hr, app, true, true)) { ... // 成功启动 } } // ActivityStack.realStartActivityLocked (核心) app.thread.scheduleLaunchActivity(...); // 通过新进程的ApplicationThread发送启动指令
-
-
新车司机拆包安装,展示货物 (新进程启动 Activity)
-
新进程的专属接线员 (
ApplicationThread) 收到scheduleLaunchActivity指令。 -
他立刻写了个便签 (
Message) 交给本进程的主管家 (H):“老板,调度中心让我们启动MainActivity!” -
主管家 (
H) 看到LAUNCH_ACTIVITY便签,调用handleLaunchActivity。 -
handleLaunchActivity做了几件大事:- 找零件: 通过
ClassLoader加载MainActivity.class。 - 造主体: 用反射 (
mInstrumentation.newActivity) 创建MainActivity对象。 - 装环境: 创建
Context(应用上下文),调用activity.attach(...)给MainActivity装上。 - 启动生命: 调用
mInstrumentation.callActivityOnCreate(activity, r.state)-> 触发MainActivity.onCreate(Bundle savedInstanceState)!App 界面开始绘制! - 展示给用户: 接着调用
handleResumeActivity-> 触发onStart()和onResume()-> 界面可见并可交互!
- 找零件: 通过
-
代码体现 (
ActivityThread.java):java Copy // H.handleMessage case LAUNCH_ACTIVITY: { ActivityClientRecord r = (ActivityClientRecord)msg.obj; handleLaunchActivity(r, null); // 处理启动 } // ActivityThread.handleLaunchActivity Activity a = performLaunchActivity(r, customIntent); // 创建、初始化、onCreate if (a != null) { handleResumeActivity(r.token, false, r.isForward); // 触发onStart, onResume } // ActivityThread.performLaunchActivity (核心) java.lang.ClassLoader cl = ...; activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent); // 反射创建Activity实例 ... // 创建Context activity.attach(...); // 绑定上下文等 if (r.state != null) { // 恢复保存的状态(如果有) mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state); } mInstrumentation.callActivityOnCreate(activity, r.state); // 调用onCreate!!! ... // 其他生命周期
-
总结一下这场“快递”接力的核心要点:
-
起点(用户): 点击图标(
Launcher)。 -
订单处理(
Launcher): 创建Intent,调用startActivity。 -
跨进程通知(
Binder IPC):Launcher->ActivityManagerService(AMS)。 -
全局调度(
AMS):- 解析
Intent,找到目标Activity和App。 - 决定启动新进程(因为
FLAG_ACTIVITY_NEW_TASK+ App未运行)。 - 暂停当前
Activity(Launcher)。 - 请求
Zygotefork 新进程。
- 解析
-
新进程初始化:
ActivityThread.main()运行,创建主线程消息循环,向AMS注册ApplicationThread(进程专属对讲机)。 -
启动指令下达(
Binder IPC):AMS-> 新进程的ApplicationThread。 -
目标
Activity诞生与展示(新进程):ApplicationThread通知主线程Handler(H)。H调用handleLaunchActivity/performLaunchActivity。- 核心动作: 反射创建
Activity实例 -> 绑定上下文 (attach) -> 调用onCreate()-> 调用onResume()。
-
终点(用户): 看到并可以操作新
App(MainActivity) 的界面。
关键角色回顾:
-
Launcher: 起点,订单发起者。 -
ActivityManagerService (AMS): 中央调度中心,管理所有Activity、Task和进程。 -
Instrumentation: 监控工具,负责调用Activity的生命周期方法。 -
ActivityThread: 每个 App 进程的主线程核心,管理本进程内的Activity生命周期、消息循环 (Looper/Handler)。它的main()是 App 进程的入口。 -
ApplicationThread:ActivityThread的内部类,是一个Binder对象(IApplicationThread.Stub)。它是 App 进程与AMS通信的桥梁。AMS通过它向 App 进程发送指令。 -
H(Handler):ActivityThread的内部类,负责在主线程处理来自ApplicationThread(即来自AMS)的消息(如LAUNCH_ACTIVITY、PAUSE_ACTIVITY)。 -
Binder IPC: 贯穿始终的跨进程通信机制。
通过这个“快递接力”的故事和关键代码节点的说明,应该能清晰地理解点击 App 图标到界面显示背后复杂的系统级协作过程了!这就是 Android 应用程序启动的源码精髓。