Activity的启动过程详细分析
Posted super码王
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Activity的启动过程详细分析相关的知识,希望对你有一定的参考价值。
前言
我们在平时开发中都知道通过这样的代码就可以启动一个Activity,如下
Context.startActivity(intent)
但是,你有没有思考这个方法的大致实现呢?下面,我们一起来看看。
startActivity的调用流程
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<IActivityTaskManager> IActivityTaskManagerSingleton =
new Singleton<IActivityTaskManager>()
@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的管理——AMS
好了,到这里,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方法:
以上是关于Activity的启动过程详细分析的主要内容,如果未能解决你的问题,请参考以下文章