Android App启动流程深度解析(一):从Activity.startActivity开始
前言
在Android应用开发中,启动流程是最基础也是最重要的机制之一。作为一名Android开发者,理解应用启动的完整流程对于性能优化、问题排查和架构设计都至关重要。本系列文章将从最上层的Activity.startActivity()
方法开始,自上而下深入分析Android应用启动的完整流程。
版本说明
本文分析的代码基于Android 10(API 29)及以上版本。在Android 10中,Google对Activity管理架构进行了重大调整:
- Android 9及之前:所有Activity相关功能由
ActivityManagerService
(AMS)统一管理 - Android 10及之后:将Activity和Task管理功能拆分到新的
ActivityTaskManagerService
(ATMS),AMS保留其他核心功能
这个变更有以下背景:
- 解耦Activity管理与系统其他核心功能
- 为多窗口、自由形态窗口等新特性提供更好的支持
- 改善系统服务的模块化程度
从Activity.startActivity开始
让我们从最常见的场景出发——一个Activity启动另一个Activity。开发者最熟悉的调用方式就是startActivity()
方法。
Activity.startActivity()
@Override
public void startActivity(Intent intent) {
this.startActivity(intent, null);
}
这是Activity
类中最简单的startActivity
重载方法。可以看到它调用了另一个重载方法,并传入了一个null的Bundle
参数。
Activity.startActivity(Intent, Bundle)
public void startActivity(Intent intent, @Nullable Bundle options) {
if (options != null) {
startActivityForResult(intent, -1, options);
} else {
startActivityForResult(intent, -1);
}
}
这个方法检查是否有附加的options Bundle,然后调用startActivityForResult()
方法。注意这里传入的requestCode是-1,表示我们不需要返回结果。
Activity.startActivityForResult()
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
@Nullable Bundle options) {
// 检查是否有父Activity
if (mParent == null) {
options = transferSpringboardActivityOptions(options);
// 关键调用
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
if (ar != null) {
mMainThread.sendActivityResult(
mToken, mEmbeddedID, requestCode, ar.getResultCode(),
ar.getResultData());
}
if (requestCode >= 0) {
mStartedActivity = true;
}
cancelInputsAndStartExitTransition(options);
} else {
// 如果有父Activity,则通过父Activity启动
if (options != null) {
mParent.startActivityFromChild(this, intent, requestCode, options);
} else {
mParent.startActivityFromChild(this, intent, requestCode);
}
}
}
这个方法有几个关键点:
- 首先检查是否有父Activity,如果没有则继续流程,否则通过父Activity启动
- 使用
Instrumentation
的execStartActivity
方法执行实际的启动操作 - 如果有返回结果,则通过
ActivityThread
发送结果 - 处理Activity过渡动画
Instrumentation.execStartActivity()
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
// 获取IApplicationThread对象
IApplicationThread whoThread = (IApplicationThread) contextThread;
// 记录来源Activity
if (mActivityMonitors != null) {
synchronized (mSync) {
final int N = mActivityMonitors.size();
for (int i=0; i<N; i++) {
final ActivityMonitor am = mActivityMonitors.get(i);
if (am.match(who, null, intent)) {
am.mHits++;
if (am.isBlocking()) {
return requestCode >= 0 ? am.getResult() : null;
}
break;
}
}
}
}
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess(who);
// 关键调用:通过ActivityTaskManager启动Activity
int result = ActivityTaskManager.getService()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, options);
// 检查启动结果
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
}
return null;
}
这个方法做了以下几件事:
- 处理ActivityMonitor(用于测试)
- 准备Intent数据
- 通过
ActivityTaskManager.getService()
获取AMS的代理对象,调用startActivity
方法 - 检查启动结果
ActivityTaskManager.getService()
public static IActivityTaskManager getService() {
return IActivityTaskManagerSingleton.get();
}
private static final Singleton<IActivityTaskManager> IActivityTaskManagerSingleton =
new Singleton<IActivityTaskManager>() {
@Override
protected IActivityTaskManager create() {
// 获取ActivityTaskManagerService的代理对象
final IBinder b = ServiceManager.getService(Context.ACTIVITY_TASK_SERVICE);
return IActivityTaskManager.Stub.asInterface(b);
}
};
这里通过Binder机制获取了系统服务ActivityTaskManagerService
的代理对象。ATMS是Android 10之后从AMS中拆分出来的专门管理Activity和Task的服务。
checkStartActivityResult()
public static void checkStartActivityResult(int res, Object intent) {
switch (res) {
case ActivityManager.START_INTENT_NOT_RESOLVED:
case ActivityManager.START_CLASS_NOT_FOUND:
throw new ActivityNotFoundException(
"Unable to find explicit activity class "
+ ((Intent)intent).getComponent().toShortString()
+ "; have you declared this activity in your AndroidManifest.xml?");
case ActivityManager.START_PERMISSION_DENIED:
throw new SecurityException("Not allowed to start activity "
+ ((Intent)intent).getComponent().toShortString());
// 其他错误处理...
}
}
这个方法将ATMS返回的结果转换为相应的异常,开发者常见的"Activity未在Manifest中声明"的错误就是在这里抛出的。
流程概览
到目前为止,我们看到的调用流程如下:
Activity.startActivity()
Activity.startActivity(Intent, Bundle)
Activity.startActivityForResult()
Instrumentation.execStartActivity()
ActivityTaskManager.getService().startActivity()
这个流程已经从应用进程进入了系统进程(system_server),后续的处理将在ATMS中进行。
为什么需要Instrumentation?
你可能注意到在流程中有一个Instrumentation
类参与其中。Instrumentation是Android测试框架的核心部分,但它也参与正常的Activity启动流程。它的主要作用有:
- 提供一种监控系统与应用交互的机制
- 在测试中可以替换组件行为
- 在正常运行时作为Activity生命周期回调的中间层
小结
本文从最常用的Activity.startActivity()
方法开始,逐步深入分析了Android应用启动的前半段流程。我们了解到:
- 启动请求最终通过
Instrumentation
转发到系统服务 - 通过Binder机制与系统服务
ActivityTaskManagerService
交互 - 基本的错误检查和处理机制
附:关键差异对比表
组件/版本 | Android 9及之前 | Android 10及之后 |
---|---|---|
核心服务 | ActivityManagerService (AMS) | ActivityTaskManagerService (ATMS) |
获取服务方式 | ActivityManager.getService() | ActivityTaskManager.getService() |
管理范围 | 包含Activity管理在内的所有功能 | 专注Activity和Task管理 |
Binder接口 | IActivityManager | IActivityTaskManager |
兼容性说明
虽然架构发生了变化,但上层API保持了兼容:
// 这两种写法在Android 10+上效果相同,但后者是推荐的新方式
startActivity(intent); // 仍然可用
ActivityTaskManager.getService().startActivity(...); // 新方式
系统通过兼容层处理了API差异,因此开发者无需修改现有代码。
为什么需要拆分ATMS?
在Android 10的架构变更中,拆分ATMS的主要考虑包括:
-
职责单一化:
- AMS原本承担了太多职责(内存管理、进程管理、Activity管理等)
- 拆分后ATMS专注于Activity和Task管理
-
多窗口支持:
- 新的多窗口模式需要更复杂的Activity栈管理
- 独立服务可以更灵活地实现这些功能
-
性能优化:
- 减少AMS的锁竞争
- 并行处理Activity相关操作
代码路径差异
在分析启动流程时,需要注意不同版本的代码路径差异:
Android 9及之前:
// 老版本通过AMS启动Activity
ActivityManager.getService().startActivity(...)
Android 10及之后:
// 新版本通过ATMS启动Activity
ActivityTaskManager.getService().startActivity(...)
原文地址:https://blog.csdn.net/liuzhuo13396/article/details/148703426
免责声明:本站文章内容转载自网络资源,如侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!