我们在平时开发中都知道通过这样的代码就可以启动一个Activity,如下
Context.startActivity(intent)
但是,你有没有思考这个方法的大致实现呢?下面,我们一起来看看。
1、一般我们都是通过调用 Activity.startActivity(intent) 来启动一个 Activity 的,紧接着它会调用其内部的startActivityForResult(intent, -1, null )方法,注意这里的requestCode==-1,因为我们不需要返回result;


2、接下来调用到了Instrumentation.execStartActivity()方法,它最终调用了如下代码:

这个 Instrumentation 是什么呢?可以说它是应用进程的管家,监控着应用进程与系统的所有交互,所有的创建、暂停、停止activity,都是通过它去发起的,它可以统计所有的开销。
那么再来看看execStartActivity()方法的内部实现:
- public ActivityResult execStartActivity(
- Context who, IBinder contextThread, IBinder token, Activity target,
- Intent intent, int requestCode, Bundle options) {
- IApplicationThread whoThread = (IApplicationThread) contextThread;
- Uri referrer = target != null ? target.onProvideReferrer() : null;
- if (referrer != null) {
- intent.putExtra(Intent.EXTRA_REFERRER, referrer);
- }
- ...
-
- try {
- intent.migrateExtraStreamToClipData();
- intent.prepareToLeaveProcess(who);
- //核心代码
- 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;
- }
这里看到Activity的启动又交给了ActivityTaskManager.getService(),这是啥?跟进去看看:
- //ActivityTaskManager
- public static IActivityTaskManager getService() {
- return IActivityTaskManagerSingleton.get();
- }
-
- private static final Singleton
IActivityTaskManagerSingleton = - new Singleton
() { - @Override
- protected IActivityTaskManager create() {
- final IBinder b = ServiceManager.getService(Context.ACTIVITY_TASK_SERVICE);
- return IActivityTaskManager.Stub.asInterface(b);
- }
- };
看到IBinder这个标志,这里你应该明白了:这里是获取一个跨进程的服务。获取的什么服务呢?是ActivityTaskManagerService(ATMS),它继承于IActivityTaskManager.Stub,是个Binder对象,并且是通过单例提供服务的。 ATMS是用于管理Activity及其容器(任务、堆栈、显示等)的系统服务,运行在系统服务进程(system_server)之中。
值得说明的是,ATMS是在Android10中新增的,分担了之前ActivityManagerService(AMS)的一部分功能(activity task相关)。
在Android10 之前 ,这个地方获取的是服务是AMS。查看Android10的AMS,你会发现startActivity方法内也是调用了ATMS的startActivity方法。所以在理解上,ATMS就隶属于AMS。
接着看,ActivityTaskManager.getService().startActivity有个返回值result,且调用了checkStartActivityResult(result, intent):
- public static void checkStartActivityResult(int res, Object intent) {
- if (!ActivityManager.isStartResultFatalError(res)) {
- return;
- }
-
- switch (res) {
- case ActivityManager.START_INTENT_NOT_RESOLVED:
- case ActivityManager.START_CLASS_NOT_FOUND:
- if (intent instanceof Intent && ((Intent)intent).getComponent() != null)
- throw new ActivityNotFoundException(
- "Unable to find explicit activity class "
- + ((Intent)intent).getComponent().toShortString()
- + "; have you declared this activity in your AndroidManifest.xml?");
- throw new ActivityNotFoundException(
- "No Activity found to handle " + intent);
- case ActivityManager.START_PERMISSION_DENIED:
- throw new SecurityException("Not allowed to start activity "
- + intent);
- ...
-
- case ActivityManager.START_CANCELED:
- throw new AndroidRuntimeException("Activity could not be started for "
- + intent);
- default:
- throw new AndroidRuntimeException("Unknown error code "
- + res + " when starting " + intent);
- }
- }
好了,到这里,Activity的启动就跨进程(IPC)的转移到系统进程提供的服务ATMS中了,接着看ATMS的startActivity
- @Override
- public int startActivityAsUser(IApplicationThread caller, String callingPackage,
- String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo,
- String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo,
- Bundle bOptions, int userId) {
- return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,
- resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions, userId,
- true /*validateIncomingUser*/);
- }
-
- private int startActivityAsUser(IApplicationThread caller, String callingPackage,
- @Nullable String callingFeatureId, Intent intent, String resolvedType,
- IBinder resultTo, String resultWho, int requestCode, int startFlags,
- ProfilerInfo profilerInfo, Bundle bOptions, int userId, boolean validateIncomingUser) {
- assertPackageMatchesCallingUid(callingPackage);
- enforceNotIsolatedCaller("startActivityAsUser");
-
- userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser,
- Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");
-
- // TODO: Switch to user app stacks here.
- return getActivityStartController().obtainStarter(intent, "startActivityAsUser")
- .setCaller(caller)
- .setCallingPackage(callingPackage)
- .setCallingFeatureId(callingFeatureId)
- .setResolvedType(resolvedType)
- .setResultTo(resultTo)
- .setResultWho(resultWho)
- .setRequestCode(requestCode)
- .setStartFlags(startFlags)
- .setProfilerInfo(profilerInfo)
- .setActivityOptions(bOptions)
- .setUserId(userId)
- .execute();
-
- }
跟到startActivityAsUser中,通过getActivityStartController().obtainStarter方法获取ActivityStarter实例 然后调用一系列方法,最后的execute()方法是开始启动activity:
res = executeRequest(mRequest); //核心代码
里面有调用了startActivityUnchecked方法,之后调用startActivityInner方法,然后调用RootActivityContainer的resumeFocusedStacksTopActivities方法。RootActivityContainer是Android10新增的类,分担了之前ActivityStackSupervisor的部分功能。接着跳转到ActivityStack的resumeTopActivityUncheckedLocked方法:
- mLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession,
- request.voiceInteractor, startFlags, true /* doResume */, checkedOptions, inTask,
- restrictedBgActivity, intentGrants);
- //ActivityStack
- @GuardedBy("mService")
- boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
- if (mInResumeTopActivity) {
- // Don't even start recursing.
- return false;
- }
-
- boolean result = false;
- try {
- // Protect against recursion.
- mInResumeTopActivity = true;
- result = resumeTopActivityInnerLocked(prev, options);
-
- // When resuming the top activity, it may be necessary to pause the top activity (for
- // example, returning to the lock screen. We suppress the normal pause logic in
- // {@link #resumeTopActivityUncheckedLocked}, since the top activity is resumed at the
- // end. We call the {@link ActivityStackSupervisor#checkReadyForSleepLocked} again here
- // to ensure any necessary pause logic occurs. In the case where the Activity will be
- // shown regardless of the lock screen, the call to
- // {@link ActivityStackSupervisor#checkReadyForSleepLocked} is skipped.
- final ActivityRecord next = topRunningActivity(true /* focusableOnly */);
- if (next == null || !next.canTurnScreenOn()) {
- checkReadyForSleep();
- }
- } finally {
- mInResumeTopActivity = false;
- }
-
- return result;
- }
跟进resumeTopActivityInnerLocked方法:
- private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
- ...
- boolean pausing = getDisplay().pauseBackStacks(userLeaving, next, false);
- if (mResumedActivity != null) {
- if (DEBUG_STATES) Slog.d(TAG_STATES,
- "resumeTopActivityLocked: Pausing " + mResumedActivity);
- // 暂停上一个Activity
- pausing |= startPausingLocked(userLeaving, false, next, false);
- }
- ...
- //这里next.attachedToProcess(),只有启动了的Activity才会返回true
- if (next.attachedToProcess()) {
- ...
-
- try {
- final ClientTransaction transaction =
- ClientTransaction.obtain(next.app.getThread(), next.appToken);
- ...
- //启动了的Activity就发送ResumeActivityItem事务给客户端了,后面会讲到
- transaction.setLifecycleStateRequest(
- ResumeActivityItem.obtain(next.app.getReportedProcState(),
- getDisplay().mDisplayContent.isNextTransitionForward()));
- mService.getLifecycleManager().scheduleTransaction(transaction);
- ....
- } catch (Exception e) {
- ....
- mStackSupervisor.startSpecificActivityLocked(next, true, false);
- return true;
- }
- ....
- } else {
- ....
- if (SHOW_APP_STARTING_PREVIEW) {
- //这里就是 冷启动时 出现白屏 的原因了:取根activity的主题背景 展示StartingWindow
- next.showStartingWindow(null , false ,false);
- }
- // 继续当前Activity,普通activity的正常启动 关注这里即可
- mStackSupervisor.startSpecificActivityLocked(next, true, true);
- }
- return true;
- }
先对上一个Activity执行pause操作,再执行当前创建操作,代码最终进入到了ActivityStackSupervisor.startSpecificActivityLocked方法中。这里有个点注意下,启动activity前调用了next.showStartingWindow方法来展示一个window,这就是冷启动时 出现白屏 的原因了。我们继续看ActivityStackSupervisor.startSpecificActivityLocked方法:
