Activity启动流程分析
我们来看⼀下 startActivity 过程的具体流程。在⼿机桌⾯应⽤中点击某⼀个 icon 之后,实际上最终就是通过 startActivity 去打开某⼀个Activity 页⾯。我们知道 Android 中的⼀个 App 就相当于⼀个进程,所以 startActivity 操作中还需要判断,⽬标 Activity 的进程是否已经创建,如果没有,则在显⽰ Activity 之前还需要将进程 Process 提前创建出来。假设是从 ActivityA 跳转到另⼀个 App 中的 ActivityB,过程如下图所⽰:spring启动流程面试回答
整个 startActivity 的流程分为 3 ⼤部分,也涉及 3 个进程之间的交互:
ActivityA --> ActivityManagerService(简称 AMS)
ActivityManagerService --> ApplicationThread
ApplicationThread --> Activity
ActivityA --> ActivityManagerService 阶段
这⼀过程并不复杂,⽤⼀张图表⽰具体过程如下:
接下来看下源码中做了哪些操作。
Activity 的 startActivity⽅法
@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
if (options != null) {
startActivityForResult(intent, -1, options);
} else {
// Note we want to go through this call for compatibility with
// applications that may have overridden the method.
startActivityForResult(intent, -1);
}
}
最终调⽤了 startActivityForResult ⽅法,传⼊的 -1 表⽰不需要获取 startActivity 的结果。
Activity 的 startActivityForResult
具体代码如下所⽰:
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
@Nullable Bundle options) {
if (mParent == null) {
options = transferSpringboardActivityOptions(options);
Instrumentation.ActivityResult ar =
this, ApplicationThread(), mToken, this,
intent, requestCode, options);
if (ar != null) {
mMainThread.sendActivityResult(
mToken, mEmbeddedID, requestCode, ar.getResultCode(),
}
if (requestCode >= 0) {
// If this start is requesting a result, we can avoid making
// the activity visible until the result is received. Setting
// this code during onCreate(Bundle savedInstanceState) or onResume() will keep the
// activity hidden during this time, to avoid flickering.
// This can only be done when a result is requested because
// that guarantees we will get information back when the
// activity is finished, no matter what happens to it.
mStartedActivity = true;
}
cancelInputsAndStartExitTransition(options);
// TODO Consider clearing/flushing other event sources and events for child windows.
} else {
if (options != null) {
mParent.startActivityFromChild(this, intent, requestCode, options);
} else {
// Note we want to go through this method for compatibility with
// existing applications that may have overridden it.
mParent.startActivityFromChild(this, intent, requestCode);
}
}
}
startActivityForResult 也很简单,调⽤ StartActivity ⽅法。剩下的交给 Instrumentation 类去处理。
解释说明:
Instrumentation 类主要⽤来监控应⽤程序与系统交互。
代码中的mMainThread 是 ActivityThread 类型,ActivityThread 可以理解为⼀个进程,在这就是 A 所在的进程。
通过 mMainThread 获取⼀个 ApplicationThread 的引⽤,这个引⽤就是⽤来实现进程间通信的,具体来说就是 AMS 所在系统进程通知应⽤程序进程进⾏的⼀系列操作。
Instrumentation 的 execStartActivity
⽅法如下:
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess(who);
int result = Service()
.startActivity(whoThread, BasePackageName(), intent,
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;
通过Service()获取获取ATMS的服务代理,跨进程调⽤ATMS的startActivity⽅法,下⼀步就ATMS内部startActivityAsUser()⽅法处理。
int startActivityAsUser(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId,
boolean validateIncomingUser) {
enforceNotIsolatedCaller("startActivityAsUser");
userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser,
// TODO: Switch to user app stacks here.
return getActivityStartController().obtainStarter(intent, "startActivityAsUser")
.setCaller(caller)
.setCallingPackage(callingPackage)
.setResolvedType(resolvedType)
.setResultTo(resultTo)
.setResultWho(resultWho)
.setRequestCode(requestCode)
.setStartFlags(startFlags)
.setProfilerInfo(profilerInfo)
.setActivityOptions(bOptions)
.setMayWait(userId)
.execute();
}
经过多个⽅法的调⽤,最终通过 obtainStarter ⽅法获取了 ActivityStarter 类型的对象,然后调⽤其 execute ⽅法。在 execute ⽅法中,会再次调⽤其内部的 startActivityMayWait ⽅法。
ActivityStarter 的 startActivityMayWait
ActivityStarter 这个类看名字就知道它专门负责⼀个 Activity 的启动操作。它的主要作⽤包括解析 Intent、创建 ActivityRecord、如果有可能还要创建 TaskRecord。startActivityMayWait ⽅法的部分实现如下:
private int startActivityMayWait(IApplicationThread caller, int callingUid,
String callingPackage, int requestRealCallingPid, int requestRealCallingUid,
Intent intent, String resolvedType, IVoiceInteractionSession voiceSession,
IVoiceInteractor voiceInteractor, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, WaitResult outResult,
Configuration globalConfig, SafeActivityOptions options, boolean ignoreTargetSecurity,
int userId, TaskRecord inTask, String reason,
boolean allowPendingRemoteAnimationRegistryLookup,
PendingIntentRecord originatingPendingIntent, boolean allowBackgroundActivityStart) {
// Refuse possible leaked file descriptors
if (intent != null && intent.hasFileDescriptors()) {
throw new IllegalArgumentException("File descriptors passed in Intent");
}
...
ResolveInfo rInfo = solveIntent(intent, resolvedType, userId,
0 /* matchFlags */,
computeResolveFilterUid(
callingUid, realCallingUid, mRequest.filterCallingUid));
if (rInfo == null) {
UserInfo userInfo = UserInfo(userId);
if (userInfo != null && userInfo.isManagedProfile()) {
// Special case for managed profiles, if attempting to launch non-cryto aware
// app in a locked managed profile from an unlocked parent allow it to resolve
// as user will be sent via confirm credentials to unlock the profile.
UserManager userManager = (mService.mContext);
boolean profileLockedAndParentUnlockingOrUnlocked = false;
long token = Binder.clearCallingIdentity();
try {
UserInfo parent = ProfileParent(userId);
profileLockedAndParentUnlockingOrUnlocked = (parent != null)
&& userManager.isUserUnlockingOrUnlocked(parent.id)
&& !userManager.isUserUnlockingOrUnlocked(userId);
} finally {
}
if (profileLockedAndParentUnlockingOrUnlocked) {
rInfo = solveIntent(intent, resolvedType, userId,
PackageManager.MATCH_DIRECT_BOOT_AWARE
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
computeResolveFilterUid(
callingUid, realCallingUid, mRequest.filterCallingUid));
}
}
}
// Collect information about the target of the Intent.
ActivityInfo aInfo = solveActivity(intent, rInfo, startFlags, profilerInfo);
...
从上图可以看出获取⽬标 Activity 信息的操作由 mSupervisor 来实现,它是 ActivityStackSupervisor 类型,从名字也能猜出它主要是负责Activity 所处栈的管理类。
resolveIntent 中实际上是调⽤系统 PackageManagerService 来获取最佳 Activity。有时候我们通过隐式 Intent 启动 Activity 时,系统中可能存在多个 Activity 可以处理 Intent,此时会弹出⼀个选择框让⽤户选择具体需要打开哪⼀个 Activity 界⾯,就是此处的逻辑处理结果。
在 startActivityMayWait ⽅法中调⽤了⼀个重载的 startActivity ⽅法,⽽最终会调⽤的 ActivityStarter 中的 startActivityUnchecked ⽅法来获取启动 Activity 的结果。
ActivityStarter 的 startActivityUnchecked
解释说明:
图中 1 处计算启动 Activity 的 Flag 值。
注释 2 处处理 Task 和 Activity 的进栈操作。
注释 3 处启动栈中顶部的 Activity。
computeLaunchingTaskFlags ⽅法具体如下:
这个⽅法的主要作⽤是计算启动 Activity 的 Flag,不同的 Flag 决定了启动 Activity 最终会被放置到哪⼀个 Task 集合中。
图中 1 处 mInTask 是 TaskRecord 类型,此处为 null,代表 Activity 要加⼊的栈不存在,因此需要判断是否需要新建 Task。
图中 2 处的 mSourceRecord 的类型 ActivityRecord 类型,它是⽤来描述“初始 Activity”,什么是“初始 Activity”呢?⽐如 ActivityA 启动了ActivityB,ActivityA 就是初始 Activity。当我们使⽤ Context 或者 Application 启动 Activity 时,此 SourceRecord 为 null。
图中 3 处表⽰初始 Activity 如果是在 SingleInstance 栈中的 Activity,这种需要添加 NEW_TASK 的标识。因为 SingleInstance 栈只能允许保存⼀个 Activity。
图中 4 处表⽰如果 Launch Mode 设置了 singleTask 或 singleInstance,则也要创建⼀个新栈。
ActivityStackSupervisor 的 startActivityLocked
⽅法中会调⽤ insertTaskAtTop ⽅法尝试将 Task 和 Activity ⼊栈。如果 Activity 是以 newTask 的模式启动或者 TASK 堆栈中不存在该
Task id,则 Task 会重新⼊栈,并且放在栈的顶部。需要注意的是:Task 先⼊栈,之后才是 Activity ⼊栈,它们是包含关系。
这⾥⼀下⼦涌出了好⼏个概念 Stack、Task、Activity,其实它们都是在 AMS 内部维护的数据结构,可以⽤⼀张图来描述它们之间的关系。
ActivityStack 的 resumeFocusedStackTopActivityLocked
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论