Android系统源码分析--Activity启动过程
关于Activity的源码分析拖延了太久的时间,由于最近工作繁忙,加上Activity启动源码非常复杂,涉及的内容很多,所以花费了很长是时间才来写这篇源码分析,希望这篇分析能让我们很容易的理解Activity的启动流程,能解决我们在使用Activity过程中遇到的问题,这样就达到了我们对于源码分析的目的了。下一篇我们介绍Activity的finish过程。
Activity启动模式简介:
我们知道Activity启动模式有四种,每一种都有不同的操作,直接影响我们App的设计,为了帮助我们理解源码,我们先分析一下这四种模式。这四种模式包括:standard, singleTop, singleTask 和 singleInstance。
(下面内容来自:Activity启动模式图文详解:standard, singleTop, singleTask 以及 singleInstance)
-
standard:标准模式,也是默认模式。这种模式是每次你调用startActivity时都会创建一个Activity实例,不管你之前有没有创建过。
-
singleTop:从名字可以分析出是顶部单例,也就是如果你要启动的Activity在任务栈的顶部,则不会在创建新的Activity实例,而是调用Activity的onNewIntent方法,如果你要启动的Activity不存在或者存在但是不在任务栈的栈顶,那么也会创建新的Activity实例并且放置到栈顶位置。因此如果你需要处理Intent中的参数,那么需要在onCreate方法和onNewIntent方法中都要处理。
-
singleTask:从名字看是单例模式,这个单例不是栈单例,而是系统单例,也就是如果系统中存在了该Activity,那么在调用startActivity时并不会重新创建一个Activity,而是将持有这个Activity的任务移动到顶部位置,并且调用onNewIntent方法,同时在这个栈中的该Activity上面的Activity都会被弹出栈并且被销毁,如果系统中不存在则会创建新的Activity,并且将这个Activity放置到一个新的任务栈中的底部(root)位置。
但是,同一个应用中,我们正常使用中同一个应用中的Activity启动却不是这样,启动的具有该属性的Activity会被放到栈的顶部,而不是放到root(底部)位置,如果需要像上面描述一样放到root位置,那么需要在AndroidManifest文件中配置Activity时添加taskAffinity属性,例如:
<activity android:name=".SingleTaskActivity" android:label="singleTask launchMode" android:launchMode="singleTask" android:taskAffinity="">
在不同的应用启动Activity,如果两个应用启动具有该属性的Activity就会创建一个新的任务,并且将该Activity放置到该任务的底部位置。除非用该属性的Activity所在的应用已经存在了,新创建该属性Activity后会将其放置到顶部位置。如果在其他的任务中存在了该属性的Activity,整个任务都会被移到顶部位置,并且该Activity上面的所有Activity都会被销毁,用户需要按back键遍历栈中的Activity才能回到调用者。
-
singleInstance:单例模式,这个模式和singleTask很相似,不同的是:持有这个Activity的任务只有一个Activity,即这个单例本身。如果这个Activity启动另一个Activity的时候会自动创建一个任务栈,并且将新启动的Activity放到该新创建的任务栈中。不过结果很怪异,当具有该模式的Activity启动另一个Activity或者另一个Activity启动具有该模式的Activity时本来需要创建一个新的任务,但是任务管理中只显示了一个(最后被移到顶部的那个),导致后台只显示一个,我们不能切换到之前的任务中。如果想切换唯一办法就是回到Launcher重新点击应用,但是显示另个一任务后,第一个任务就会被隐藏了。也就是切换后还是只能显示一个任务。如果想要解决仍然需要设置taskAffinity属性,例如:
<activity android:name=".SingleTaskActivity" android:label="singleTask launchMode" android:launchMode="singleTask" android:taskAffinity="">
这样就正常了,这种模式很少使用,除非想Launcher这种只有一个Activity,或者100%确定只有一个Activity。
Activity源码解析
要了解Activity启动的过程不仅要知道代码流程,也要知道设计流程,我们先看代码流程,分析完成后我们再重新看一下设计流程,来帮助我们记忆源码流程。因为篇幅比较长,我们下面分为两个部分分析。
第一部分:
ActivityStart1.jpgStep1.startActivityForResult:
Activity的启动一般有了两种方式,一种是需要返回结果的,一种是不需要返回结果的。这里的函数和我们上面时序图中的不一样,其实最终调用的方法是这个,另外还有几个参数不同的方法,其实是一样的,我们看最终调用代码:
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
@Nullable Bundle options) {
if (mParent == null) {
...
// Instrumentation是用来监控程序与系统之间的交互操作的,mMainThread的类型为ActivityThread,
// 是用来描述应用程序进程的,系统每当启动一个应用程序进程时,都会在它里面加载一个ActivityThread
// 类实体,并且这个类实体会保存在每一个在该进程中启动的Activity组件的父类Activity的成员变量
// mMainThread中。ActivityThread的成员函数getApplicationThread用来获取它内部一个类型为
// ApplicationThread对象作为参数传递给变量mInstrumentation的成员函数execStartActivity,
// 以便将它传递给AMS,这样就可以通过ApplicationThread与Activity交流了。Activity的成员变量
// mToken的类型为IBinder,它是Binder代理对象,指向AMS中一个类型为ActivityRecord对象,用来维护
// 对应的Activity组件的运行状态以及信息。此处传入也是为了传递给AMS,这样AMS就可以得到Activity的
// 详细信息了。
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());
}
...
} else {
...
}
}
直接启动时参数requestCode为-1,这里执行调用Instrumentation.execStartActivity方法,后面执行ActivityThread.sendActivityResult返回结果,这个方法我们后面会分析,这里不再分析,我们先看启动的方法:
Step2.Instrumentation.execStartActivity
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
...
// 获取AMS的代理对象AMP(ActivityManagerProxy),然后调用起startActivity方法,通过该方法
// 通知AMS启动Activity
int result = ActivityManagerNative.getDefault()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, options);
...
return null;
}
这个方法传入有个参数target,从上面代码可知传入的是this,也就是调用启动Activity方法的Activity,我们称之为调用者或者源Activity。这里主要是调用startActivity方法,这里的ActivityManagerNative.getDefault()我们在前面的文字介绍过是ActivityManagerProxy。
Step3.ActivityManagerProxy.startActivity
public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {
...
// 通过AMP类内部的一个IBinder代理对象想AMS发送一个类型为START_ACTIVITY_TRANSACTION的进程间通信请求
mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
...
return result;
}
最终调用AMS(ActivityManagerService)的startActivity方法。
Step4.AMS.startActivity
public final int startActivity(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
resultWho, requestCode, startFlags, profilerInfo, bOptions,
UserHandle.getCallingUserId());
}
然后调用startActivityAsUser方法。
Step5.AMS.startActivityAsUser
public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
...
// mActivityStarter是Activity启动等操作的管理者
return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
profilerInfo, null, null, bOptions, false, userId, null, null);
}
调用ActivityStarter.startActivityMayWait方法。
Step6.ActivityStarter.startActivityMayWait
// 该函数的Wait表示对于outResult的处理上
final int startActivityMayWait(IApplicationThread caller, int callingUid,
String callingPackage, Intent intent, String resolvedType,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
IBinder resultTo, String resultWho, int requestCode, int startFlags,
ProfilerInfo profilerInfo, IActivityManager.WaitResult outResult, Configuration config,
Bundle bOptions, boolean ignoreTargetSecurity, int userId,
IActivityContainer iContainer, TaskRecord inTask) {
...
// 是否指定了要启动Activity相关的组件名,如果指定了组件名则为显示启动,否则为隐式启动
boolean componentSpecified = intent.getComponent() != null;
...
// 收集Intent中的信息
...
synchronized (mService) {
...
final ActivityRecord[] outRecord = new ActivityRecord[1];
int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
aInfo, rInfo, voiceSession, voiceInteractor,
resultTo, resultWho, requestCode, callingPid,
callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
options, ignoreTargetSecurity, componentSpecified, outRecord, container,
inTask);
...
return res;
}
}
这里主要是收集Intent的内容,进行判断整理,然后调用startActivityLocked方法。
Step7.startActivityLocked
// Locked 代表非线程安全的,提醒我们必须保证这些函数是线程安全的,(因为他们涉及不可重入资源的处理)
final int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
TaskRecord inTask) {
int err = ActivityManager.START_SUCCESS;
// 获取调用者进程记录对象,每一个进程都使用一个ProcessRecord对象来描述,并且会保存起来
ProcessRecord callerApp = null;
if (caller != null) {
// mService指向AMS,通过caller来获取对应的ProcessRecord对象callerApp,参数caller指向
// 启动Activity的组件所运行在的应用程序进程的一个ApplicationThread对象,因此ProcessRecord
// 对象callerApp指向了启动者所在的应用程序进程(正在启动的为被调用者)。
callerApp = mService.getRecordForAppLocked(caller);
if (callerApp != null) {// 调用者进程存在
callingPid = callerApp.pid;
callingUid = callerApp.info.uid;
} else {// 调用者被系统杀死或者意外退出
...
}
}
...
ActivityRecord sourceRecord = null;// 调用者Activity封装
ActivityRecord resultRecord = null;// 需要接受返回结果的Activity对象封装
if (resultTo != null) {// 需要返回结果
// 查找所有栈中是否存在对应resultTo(调用者)的ActivityRecord
sourceRecord = mSupervisor.isInAnyStackLocked(resultTo);
if (sourceRecord != null) {
// 如果requestCode大于等于0(也就是需要返回结果的启动Activity),
// 并且请求者的Activity没有在等待finish队列中,说明sourceRecord就是接受结果的Activity
if (requestCode >= 0 && !sourceRecord.finishing) {
// 将启动者的Activity作为接受结果的Activity
resultRecord = sourceRecord;
}
}
}
final int launchFlags = intent.getFlags();
// 直接启动Activity时requestCode为-1,因此sourceRecord为空,resultRecord为空
// 这里对标志位Intent.FLAG_ACTIVITY_FORWARD_RESULT进行了判断,我们先解释一下这个标志位:如果A启动了B
// 并且需要返回结果,而B需要启动了C从C返回结果给A,那么B需要设置Intent.FLAG_ACTIVITY_FORWARD_RESULT标志
// 位,并且为了避免冲突B在启动C时不需要再设置requestCode,而此时sourceRecord是B,resultRecord是A,
// 就是下面代码的解释,设置该标志后,C调用setResult时结果不会传递给B而是传递给A。
if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
// Transfer the result target from the source activity to the new
// one being started, including any failures.
// 这里requestCode是B传过来的,如果设置了上面的标签,B就不能再设置requestCode,因此,如果
// requestCode>=0就会产生冲突,因此B不能再设置requestCode
if (requestCode >= 0) {
ActivityOptions.abort(options);
return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
}
// 如果设置了上面的标签,最终的接受结果的Activity就是B(sourceRecord)中resultTo指向的Activity而不是B
resultRecord = sourceRecord.resultTo;
// 如果启动者resultRecord不在栈中,赋值为空
if (resultRecord != null && !resultRecord.isInStackLocked()) {
resultRecord = null;
}
...
requestCode = sourceRecord.requestCode;// 传递requestCode
...
if (resultRecord != null) {// 还存在栈中,移除结果
resultRecord.removeResultsLocked(sourceRecord, resultWho, requestCode);
}
...
}
...
// 不需要返回结果直接启动Activity时resultRecord为空
final ActivityStack resultStack = resultRecord == null ? null : resultRecord.task.stack;
if (err != START_SUCCESS) {// 失败
if (resultRecord != null) {
// 需要返回结果的启动Activity,调用Activity.onActivityResult,返回操作取消的结果
resultStack.sendActivityResultLocked(
-1, resultRecord, resultWho, requestCode, RESULT_CANCELED, null);
}
ActivityOptions.abort(options);
return err;
}
...
if (abort) {// 如果终止
if (resultRecord != null) {
// 等待返回结果的Activity,调用Activity.onActivityResult方法,返回取消操作的结果
resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
RESULT_CANCELED, null);
}
ActivityOptions.abort(options);
return START_SUCCESS;
}
// 创建一个ActivityRecord对象r来描述即将被启动的Activity组件
ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
requestCode, componentSpecified, voiceSession != null, mSupervisor, container,
options, sourceRecord);
if (outActivity != null) {
outActivity[0] = r;
}
...
// 获取栈
final ActivityStack stack = mSupervisor.mFocusedStack;
// 前面voiceSession传入为空,并且没有可恢复的Activity或者可恢复的Activity不是当前调用者
if (voiceSession == null && (stack.mResumedActivity == null
|| stack.mResumedActivity.info.applicationInfo.uid != callingUid)) {
// 前台栈(stack)还没有resume状态的Activity时, 则检查app切换是否允许,不允许切换则要放入等待列表
if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
realCallingPid, realCallingUid, "Activity start")) {
// 不许切换时,获取启动新Activity请求的描述,放到等待列表
PendingActivityLaunch pal = new PendingActivityLaunch(r,
sourceRecord, startFlags, stack, callerApp);
// 添加PendingActivityLaunch
mPendingActivityLaunches.add(pal);
ActivityOptions.abort(options);
return ActivityManager.START_SWITCHES_CANCELED;
}
}
// 允许切换
if (mService.mDidAppSwitch) {
mService.mAppSwitchesAllowedTime = 0;// 将切换时间设置为0
} else {
mService.mDidAppSwitch = true;
}
// 处理等待启动的Activity
doPendingActivityLaunchesLocked(false);
try {
...
// 启动目标Activity操作
err = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
true, options, inTask);
} finally {
mService.mWindowManager.continueSurfaceLayout();
}
postStartActivityUncheckedProcessing(r, err, stack.mStackId, mSourceRecord, mTargetStack);
return err;
}
上面代码注释比较详细,有一点我们提一下就是FLAG_ACTIVITY_FORWARD_RESULT标签,也就是我们在开发中遇到的一种情况,ActivityA启动ActivityB,ActivityB启动ActivityC,C返回结果让A接收,我们平时不知道怎么处理,通过上面源码我们看到可以设置这个标签,就可以完成我们需要的操作。
上面我们在启动失败的时候回直接返回结果,中断操作,调用ActivityStack.sendActivityResultLocked方法。
Step8.ActivityStack.sendActivityResultLocked
void sendActivityResultLocked(int callingUid, ActivityRecord r,
String resultWho, int requestCode, int resultCode, Intent data) {
...
if (mResumedActivity == r && r.app != null && r.app.thread != null) {
try {
...
r.app.thread.scheduleSendResult(r.appToken, list);
return;
}
...
}
...
}
这里会调用ApplicationThreadProxy.scheduleSendResult方法。
Step9.ApplicationThreadProxy.scheduleSendResult
public final void scheduleSendResult(IBinder token, List<ResultInfo> results)
throws RemoteException {
...
mRemote.transact(SCHEDULE_SEND_RESULT_TRANSACTION, data, null,
IBinder.FLAG_ONEWAY);
data.recycle();
}
这个我们之前在上一章分析广播的时候讲过的,最终会调用ActivityThread.scheduleSendResult方法。
Step10.ActivityThread.scheduleSendResult
public final void scheduleSendResult(IBinder token, List<ResultInfo> results) {
...
sendMessage(H.SEND_RESULT, res);
}
这里通过Handler发送消息到ActivityThread.H.handleMessage中进行处理。然后调用handleSendResult方法
Step12.ActivityThread.handleSendResult
private void handleSendResult(ResultData res) {
...
if (r != null) {
final boolean resumed = !r.paused;
...
deliverResults(r, res.results);
if (resumed) {
r.activity.performResume();
r.activity.mTemporaryPause = false;
}
}
}
这里调用deliverResults方法分发结果,分发完成如果需要复用的,则调用复用方法,这个我们后面会介绍到。
Step13.ActivityThread.deliverResults
private void deliverResults(ActivityClientRecord r, List<ResultInfo> results) {
final int N = results.size();
for (int i = 0; i < N; i++) {
...
r.activity.dispatchActivityResult(ri.mResultWho,
ri.mRequestCode, ri.mResultCode, ri.mData);
...
}
}
这里调用Activity.dispatchActivityResult方法分发结果。
Step14.Activity.dispatchActivityResult
void dispatchActivityResult(String who, int requestCode,
int resultCode, Intent data) {
....
onActivityResult(requestCode, resultCode, data);
...
}
这里会调用onActivityResult方法,返回结果,其他的情况这里不介绍了,自己分析一下就好了。到此结果返回就完成了,我们接着分析,再回到Step7,这个方法中有几个发送返回结果的调用,其实调用都是一样的,接着我们分析下面的代码,调用doPendingActivityLaunchesLocked方法,后面还有startActivityUnchecked方法和postStartActivityUncheckedProcessing方法,其实这两个方法也是重复调用,也就是doPendingActivityLaunchesLocked里面也调用了这两个方法,因此我们只分析一次就好了。我们从doPendingActivityLaunchesLocked方法开始分析。
Step16.ActivityStarter.doPendingActivityLaunchesLocked
// 启动等待列表中的Activity,参数doResume传递过来是false
final void doPendingActivityLaunchesLocked(boolean doResume) {
while (!mPendingActivityLaunches.isEmpty()) {
final PendingActivityLaunch pal = mPendingActivityLaunches.remove(0);
// 如果mPendingActivityLaunches列表中没有了并且需要复用时设置为复用,这里是false
// (等待列表中最后一个是最后加进来的,所以需要复用时选择最近的一个进行复用)
final boolean resume = doResume && mPendingActivityLaunches.isEmpty();
...
final int result = startActivityUnchecked(
pal.r, pal.sourceRecord, null, null, pal.startFlags, resume, null, null);
...
}
}
这里我们看到了调用了startActivityUnchecked方法和postStartActivityUncheckedProcessing方法,主要的处理都在startActivityUnchecked方法中,所以下面我们主要看startActivityUnchecked方法,这个方法调用结束启动也就结束了。
Step17.ActivityStarter.startActivityUnchecked
/**
* 这个方法调用有两个地方,一个是处理等待的Activity,一个是正常启动Activity
*
* @param r 描述需要被启动的Activity的对象
* @param sourceRecord 调用者的Activity的封装
* @param voiceSession 等待的为空,否则不为空
* @param voiceInteractor 等待的为空,否则不为空
* @param startFlags 0
* @param doResume 是否需要复用,等待的不一定需要,直接启动的需要复用
* @param options 等待的为空,否则不为空
* @param inTask 等待的为空,否则不为空
*
* @return
*/
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {
// 设置初始状态
setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
voiceInteractor);
computeLaunchingTaskFlags();
computeSourceStack();
mIntent.setFlags(mLaunchFlags);
// 查找有没有可复用的Activity
mReusedActivity = getReusableIntentActivity();
...
// 如果有可复用的Activity
if (mReusedActivity != null) {
...
// mStartActivity是在setInitialState方法中赋值的,指向的是被启动Activity对象封装,
// 如果是第一次启动那么它的任务栈就不存在,此时先默认设置成启动Activity的任务栈。
if (mStartActivity.task == null) {
mStartActivity.task = mReusedActivity.task;
}
...
// 这里有三个条件,只需要满足一个就执行if语句中的操作
// 1.需要清理能复用的Activity所在栈中该Activity上面的其他Activity,
// 2.该Activity是SingleInstance模式
// 3.该Activity是SingleTask模式
if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
|| mLaunchSingleInstance || mLaunchSingleTask) {
// 获取要启动Activity
final ActivityRecord top = mReusedActivity.task.performClearTaskForReuseLocked(
mStartActivity, mLaunchFlags);
if (top != null) {
...
top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
mStartActivity.launchedFromPackage);
}
}
sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);
// 将可复用的Activity移到栈顶
mReusedActivity = setTargetStackAndMoveToFrontIfNeeded(mReusedActivity);
if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
resumeTargetStackIfNeeded();
return START_RETURN_INTENT_TO_CALLER;
}
setTaskFromIntentActivity(mReusedActivity);
// 如果不需要添加到任务栈,并且复用TaskRecord为空,说明没有启动一个新的Activity
// mAddingToTask为false表示要为目标Activity组件创建一个专属任务,事实上函数会检查这个专属
// 任务是否存在,如果已存在,那么就会将变量mAddingToTask的值设置为true,
if (!mAddingToTask && mReuseTask == null) {
// We didn't do anything... but it was needed (a.k.a., client don't use that
// intent!) And for paranoia, make sure we have correctly resumed the top activity.
resumeTargetStackIfNeeded();
// 需要启动的Activity不需要重启启动,只需要将其放到栈顶即可
return START_TASK_TO_FRONT;
}
}
// 找不到对应类(Activity)
if (mStartActivity.packageName == null) {
if (mStartActivity.resultTo != null && mStartActivity.resultTo.task.stack != null) {
mStartActivity.resultTo.task.stack.sendActivityResultLocked(
-1, mStartActivity.resultTo, mStartActivity.resultWho,
mStartActivity.requestCode, RESULT_CANCELED, null);
}
ActivityOptions.abort(mOptions);
return START_CLASS_NOT_FOUND;
}
// If the activity being launched is the same as the one currently at the top, then
// we need to check if it should only be launched once.
final ActivityStack topStack = mSupervisor.mFocusedStack;
final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
...
if (dontStart) {// 不启动
...
topStack.mLastPausedActivity = null;
if (mDoResume) {
mSupervisor.resumeFocusedStackTopActivityLocked();
}
...
top.deliverNewIntentLocked(
mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
...
// 需要启动的Activity在栈顶
return START_DELIVERED_TO_TOP;
}
boolean newTask = false;// 是否会新创建一个任务
// Activity组件中有一个android:taskAffinity属性,用来描述它的一个专属任务,当AMS决定要将目标
// Activity运行在一个不同的任务中时,AMS就会检查目标Activity组件的专属任务是否已经存在,如果存
// 在,那么AMS就会直接将目标Activity组件添加到它里面运行,否则,就会先创建这个专属任务,然后将目
// 标Activity组件添加到它里面去运行
final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
? mSourceRecord.task : null;
// Should this be considered a new task?
if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
&& (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
newTask = true;
setTaskFromReuseOrCreateNewTask(taskToAffiliate);
...
} else if (mSourceRecord != null) {
...
final int result = setTaskFromSourceRecord();
...
} else if (mInTask != null) {
...
final int result = setTaskFromInTask();
...
} else {
...
setTaskToCurrentTopOrCreateNewTask();
}
...
mTargetStack.startActivityLocked(mStartActivity, newTask, mKeepCurTransition, mOptions);
if (mDoResume) {
if (!mLaunchTaskBehind) {
// TODO(b/26381750): Remove this code after verification that all the decision
// points above moved targetStack to the front which will also set the focus
// activity.
mService.setFocusedActivityLocked(mStartActivity, "startedActivity");
}
// 获取顶部ActivityRecord
final ActivityRecord topTaskActivity = mStartActivity.task.topRunningActivityLocked();
...
// 恢复聚焦栈顶Activity
mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
mOptions);
...
} else {
// 添加启动的Activity到最近任务
mTargetStack.addRecentActivityLocked(mStartActivity);
}
mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
...
return START_SUCCESS;
}
Activity的启动最核心的东西就在这个方法中,所以这个方法会很复杂,里面调用了很多方法,每个方法分析都会比较复杂,在这个方法最后返回成功,也就是Activity的启动结束标志。下面我们具体分析每一步的具体内容,让我们彻底了解Activity的启动流程。
Step18.ActivityStarter.setInitialState
private void setInitialState(ActivityRecord r, ActivityOptions options, TaskRecord inTask,
boolean doResume, int startFlags, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
reset();// 初始化参数
mStartActivity = r;// 对mStartActivity赋值,也就是被启动的Activity的对象封装
...
// 判断启动模式,因为默认是standard模式,所以只需要与其他三个对比就可以了
mLaunchSingleTop = r.launchMode == LAUNCH_SINGLE_TOP;
mLaunchSingleInstance = r.launchMode == LAUNCH_SINGLE_INSTANCE;
mLaunchSingleTask = r.launchMode == LAUNCH_SINGLE_TASK;
mLaunchFlags = adjustLaunchFlagsToDocumentMode(
r, mLaunchSingleInstance, mLaunchSingleTask, mIntent.getFlags());
// 通过ActivityOptions.setLaunchTaskBehind方法被激活,并且被启动完成后就会被清理
mLaunchTaskBehind = r.mLaunchTaskBehind
&& !mLaunchSingleTask && !mLaunchSingleInstance
&& (mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0;
sendNewTaskResultRequestIfNeeded();
...
// We'll invoke onUserLeaving before onPause only if the launching
// activity did not explicitly state that this is an automated launch.
// 检查变量mLaunchFlags的Intent.FLAG_ACTIVITY_NO_USER_ACTION位是否为1,如果等于1,那么就
// 表示目标Activity组件不是由用户手动启动的,如果目标Activity组件是由用户手动启动的,那么用来
// 启动它的源Activity组件就会获得一个用户离开时间通知,由于目标Activity组件使用户在应用程序启
// 动器的界面上点击启动的,即变量mLaunchFlags的Intent.FLAG_ACTIVITY_NO_USER_ACTION位等于0,
// 因此,成员变量mUserLeaving的值为true。
mSupervisor.mUserLeaving = (mLaunchFlags & FLAG_ACTIVITY_NO_USER_ACTION) == 0;
...
if (mOptions != null && mOptions.getLaunchTaskId() != -1 && mOptions.getTaskOverlay()) {
r.mTaskOverlay = true;
// 查找所有的栈是否存在对应的TaskRecord
final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
// 如果存在TaskRecord,那么获取顶部Activity的ActivityRecord
final ActivityRecord top = task != null ? task.getTopActivity() : null;
...
}
// intent的标志值的位Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP也没有置位,因此,变量notTop的值为null。
mNotTop = (mLaunchFlags & FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
...
}
这个方法里面主要是数据初始化,判断启动模式,获取启动标签,为启动Activity做准备。
Step19.ActivityStarter.adjustLaunchFlagsToDocumentMode
/**
* 从前面调用可知,launchFlags是从Intent中获取的,是目标Activity组件启动的标志位,在launchFlags中,
* 只有Intent.FLAG_ACTIVITY_NEW_TASK位被标记为1,其它位都为0.
*
* @param r 被启动Activity对象封装
* @param launchSingleInstance 是不是SingleInstance模式
* @param launchSingleTask 是不是SingleTask模式
* @param launchFlags 启动标记
*
* @return
*/
private int adjustLaunchFlagsToDocumentMode(ActivityRecord r, boolean launchSingleInstance,
boolean launchSingleTask, int launchFlags) {
// 如果launchFlags是FLAG_ACTIVITY_NEW_DOCUMENT模式并且启动模式是singleInstance或者singleTask
if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
(launchSingleInstance || launchSingleTask)) {
// 如果Intent中的标记为和manifest中的有冲突,则以manifest中的为主
launchFlags &=
~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_MULTIPLE_TASK);
} else {
...
}
return launchFlags;
}
这个方法主要是判断启动标签,这里有个提示,就是如果动态设置的标签和AndroidManifest里面配置的冲突,那么以Manifest文件中为准。
Step20.ActivityStarter.sendNewTaskResultRequestIfNeeded
private void sendNewTaskResultRequestIfNeeded() {
// 发送条件:接收结果的Activity存在,并且mLaunchFlags是FLAG_ACTIVITY_NEW_TASK,并且接收结果的任务栈存在
if (mStartActivity.resultTo != null && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0
&& mStartActivity.resultTo.task.stack != null) {
...
mStartActivity.resultTo.task.stack.sendActivityResultLocked(-1, mStartActivity.resultTo,
mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED, null);
...
}
}
这里又调用了上面第8步的过程--sendActivityResultLocked方法,这里就不再介绍了,没记住的可以回去看8-14步就可以了。
Step21.ActivityStack.sendActivityResultLocked
void sendActivityResultLocked(int callingUid, ActivityRecord r,
String resultWho, int requestCode, int resultCode, Intent data) {
...
// 调用onActivityResult
r.app.thread.scheduleSendResult(r.appToken, list);
...
}
这个过程和上面9-15一样,所以不再讲解。
Step23.ActivityStackSupervisor.anyTaskForIdLocked
调用下面代码。
Step24.ActivityStackSupervisor.anyTaskForIdLocked
TaskRecord anyTaskForIdLocked(int id, boolean restoreFromRecents, int stackId) {
// 这里的多个显示一般是可能存在多窗口模式,每一个窗口用ActivityDisplay来表示,它包含了当前窗口存在的所
// 有栈,这里遍历所有显示任务栈中,查找有没有对应id的任务。
int numDisplays = mActivityDisplays.size();
for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
ActivityStack stack = stacks.get(stackNdx);
TaskRecord task = stack.taskForIdLocked(id);
if (task != null) {
return task;
}
}
}
// 根据任务id查找最近任务列表中是否存在该认为
TaskRecord task = mRecentTasks.taskForIdLocked(id);
...
return task;
}
这个方法主要是根据任务栈id查找所有屏幕显示的任务列表中是否存在该id对应的任务,如果有直接返回,如果没有从最近任务中查找,没有直接返回null,如果有则调用restoreRecentTaskLocked方法存储该任务。
Step25.ActivityStackSupervisor.restoreRecentTaskLocked
private boolean restoreRecentTaskLocked(TaskRecord task, int stackId) {
if (stackId == INVALID_STACK_ID) {// 无效的id,我们前面传入的就是这个无效的id
stackId = task.getLaunchStackId();// 获取当前任务的id
} else if (stackId == DOCKED_STACK_ID && !task.canGoInDockedStack()) {
...
} else if (stackId == FREEFORM_WORKSPACE_STACK_ID
&& mService.mUserController.shouldConfirmCredentials(task.userId)) {
...
}
// 当前任务中的栈管理不为空,说明已经保存了该任务
if (task.stack != null) {
// Task has already been restored once. See if we need to do anything more
if (task.stack.mStackId == stackId) {// 这里判断任务栈是否在对的栈管理中。
// Nothing else to do since it is already restored in the right stack.
return true;
}
// 如果我们的任务不在对的栈管理中,我们需要先移除该任务,然后与正确的栈管理进行关联。
task.stack.removeTask(task, "restoreRecentTaskLocked", REMOVE_TASK_MODE_MOVING);
}
...
stack.addTask(task, false, "restoreRecentTask");
...
return true;
}
Step26.ActivityStack.removeTask
void removeTask(TaskRecord task, String reason, int mode) {
if (mode == REMOVE_TASK_MODE_DESTROYING) {// 长在被完全移除栈
mStackSupervisor.removeLockedTaskLocked(task);// 移除锁定任务
...
}
final ActivityRecord r = mResumedActivity;
if (r != null && r.task == task) {// 存在可复用的Activity,并且是我们正要启动的Activity
mResumedActivity = null;
}
final int taskNdx = mTaskHistory.indexOf(task);
final int topTaskNdx = mTaskHistory.size() - 1;
if (task.isOverHomeStack() && taskNdx < topTaskNdx) {
// 获取要移除任务的下一个任务
final TaskRecord nextTask = mTaskHistory.get(taskNdx + 1);
...
}
mTaskHistory.remove(task);// 从历史记录移除
updateTaskMovement(task, true);
// 该任务模式为正在被移除销毁,并且该任务中没有已经启动的Activity
if (mode == REMOVE_TASK_MODE_DESTROYING && task.mActivities.isEmpty()) {
...
// 这里判断是否从最近任务移除该任务
if (task.autoRemoveFromRecents() || isVoiceSession) {
...
}
}
// 该栈管理中的历史任务为空,也就是全部被清理了或者没有启动任务
if (mTaskHistory.isEmpty()) {
...
}
task.stack = null;
}
从当前栈中移除传入的任务。
Step27.ActivityStack.addTask
void addTask(final TaskRecord task, final boolean toTop, String reason) {
final ActivityStack prevStack = preAddTask(task, reason, toTop);
task.stack = this;
if (toTop) {
insertTaskAtTop(task, null);
} else {// 直接插入到历史任务的最顶部
mTaskHistory.add(0, task);
updateTaskMovement(task, false);
}
postAddTask(task, prevStack);
}
将任务插入到栈中,这里面有个insertTaskAtTop我们后面再讲。
Step28.ActivityStater.computeLaunchingTaskFlags
这个方法主要是对于mLauncherFlags的处理,这里就不再贴代码。
Step29.ActivityStater.computeSourceStack
private void computeSourceStack() {
// 当前Activity不存在了
if (mSourceRecord == null) {
mSourceStack = null;
return;
}
// 如果当前Activity没有被finish
if (!mSourceRecord.finishing) {
mSourceStack = mSourceRecord.task.stack;
return;
}
...
// 如果当前Activity正在被finish,并且启动模式不是启动一个新的任务,那么我们要添加启动新任务的标签。
if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0) {
Slog.w(TAG, "startActivity called from finishing " + mSourceRecord
+ "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
mNewTaskInfo = mSourceRecord.info;
mNewTaskIntent = mSourceRecord.task.intent;
}
mSourceRecord = null;
mSourceStack = null;
}
这里主要是获取mSourceStack是否存在。
Step30.ActivityStater.getReusableIntentActivity
/**
* 决定新的Activity是否应该被插入到已经存在的任务栈中。如果不插入,返回null,
* 否则返回一个带有新Activity加入的任务栈的ActivityRecord
*/
private ActivityRecord getReusableIntentActivity() {
// 是否放置到已经存在的任务栈中
boolean putIntoExistingTask = ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 &&
(mLaunchFlags & FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
|| mLaunchSingleInstance || mLaunchSingleTask;
...
ActivityRecord intentActivity = null;
if (mOptions != null && mOptions.getLaunchTaskId() != -1) {
// 根据Id获取任务
final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
// 如果任务存在启动的Activity就是任务中顶部的Activity
intentActivity = task != null ? task.getTopActivity() : null;
} else if (putIntoExistingTask) {// 如果需要放到已存在任务中
if (mLaunchSingleInstance) {// SingleInstance模式下,在历史记录中只有一个Activity的实例,并且它一直在它独有的任务栈中。
intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info, false);
} else if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {// 是不是分屏模式
intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
!mLaunchSingleTask);
} else {
intentActivity = mSupervisor.findTaskLocked(mStartActivity);
}
}
return intentActivity;
}
这里是获取一个可复用的Activity,可能存在,也可能为null。
Step31.ActivityStackSupervisor.anyTaskForIdLocked
这里方法和上面23一样,所以不在讲解,我们接着看36步。
Step36.ActivityStackSupervisor.findActivityLocked
// 查找栈中是否存在与被启动Activity相同的Activity,如果存在取第一个返回,不存在返回空
ActivityRecord findActivityLocked(Intent intent, ActivityInfo info,
boolean compareIntentFilters) {
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityRecord ar = stacks.get(stackNdx)
.findActivityLocked(intent, info, compareIntentFilters);
if (ar != null) {
return ar;
}
}
}
return null;
}
根据for循环来查找对应的Activity。
Step37.ActivityStack.findActivityLocked
ActivityRecord findActivityLocked(Intent intent, ActivityInfo info,
boolean compareIntentFilters) {
...
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
...
}
return null;
}
从栈顶开始,返回第一个与该要启动的Activity相同的Activity,如果没有则返回空
Step38.ActivityStackSupervisor.findTaskLocked
ActivityRecord findTaskLocked(ActivityRecord r) {
...
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
...
// 查找栈中是否存在对应的Activity
stack.findTaskLocked(r, mTmpFindTaskResult);
..
}
}
if (DEBUG_TASKS && mTmpFindTaskResult.r == null) Slog.d(TAG_TASKS, "No task found");
return mTmpFindTaskResult.r;
}
这里考虑到了分屏,查找所有屏幕上是否存在对应的Activity。
Step39.ActivityStack.findTaskLocked
这个方法没有太复杂的东西,所以不再贴代码,主要根据传入的参数查找存在该Activity的task。
Step40.TaskRecord.performClearTaskForReuseLocked
ActivityRecord performClearTaskForReuseLocked(ActivityRecord newR, int launchFlags) {
...
final ActivityRecord result = performClearTaskLocked(newR, launchFlags);
...
}
调用performClearTaskLocked方法:
Step41.TaskRecord.performClearTaskLocked
final ActivityRecord performClearTaskLocked(ActivityRecord newR, int launchFlags) {
int numActivities = mActivities.size();
for (int activityNdx = numActivities - 1; activityNdx >= 0; --activityNdx) {
ActivityRecord r = mActivities.get(activityNdx);
if (r.finishing) {// 如果正在finish过滤掉
continue;
}
// 如果是要找的Activity,则finish掉所在栈中上面的所有Activity
if (r.realActivity.equals(newR.realActivity)) {// 判断ComponentName(包名类名)
// Here it is! Now finish everything in front...
// 如果包名类名一样,则说明就是要找的和被启动Activity一样的Activity,其实就是要启动这个Activity
final ActivityRecord ret = r;
for (++activityNdx; activityNdx < numActivities; ++activityNdx) {
r = mActivities.get(activityNdx);
if (r.finishing) {
continue;
}
...
// 开始清理要启动的Activity上面的Activity
if (stack != null && stack.finishActivityLocked(
r, Activity.RESULT_CANCELED, null, "clear-task-stack", false)) {
--activityNdx;
--numActivities;
}
}
...
}
}
return null;
}
这里主要是要清理可复用Activity栈中该Activity顶部的Activity,清理调用ActivityStack.finishActivityLocked方法进行清理,这个方法我们在下一章Activity的finish过程再讲。
Step43.ActivityRecord.deliverNewIntentLocked
final void deliverNewIntentLocked(int callingUid, Intent intent, String referrer) {
...
// 如果正在启动的Activity已经存在,不需要创建新的Activity,则会调用Activity中的onNewIntent
app.thread.scheduleNewIntent(
ar, appToken, state == ActivityState.PAUSED /* andPause */);
...
}
清理完成后,该可复用Activity就会到达栈顶,此时要调用onNewIntent方法,调用过程就是上面scheduleNewIntent开始,后面的步骤和上面10-15基本一样所以不再详细讲解,其实从广播到Activity启动声明周期或者内部方法的调用都是一样的过程,你只要熟悉一个方法的过程,所有方法的过程就全部都会了,所以这里还是比较容易学习的。
Step52.ActivityStarter.setTargetStackAndMoveToFrontIfNeeded
如果可复用的Activity存在那么就要设置并且将其移到最前面来,也就是栈顶。
private ActivityRecord setTargetStackAndMoveToFrontIfNeeded(ActivityRecord intentActivity) {
// 将要启动的Activity所在任务所在的栈作为目标栈
mTargetStack = intentActivity.task.stack;
...
// 获取当前焦点栈
final ActivityStack focusStack = mSupervisor.getFocusedStack();
// 获取焦点栈中最上面正在运行的非延迟Activity
ActivityRecord curTop = (focusStack == null)
? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
// 这里三个条件:
// 1.存在上面获取的Activity,
// 2.该Activity和要启动Activity不在同一个任务,或者该Activity不是最顶部的任务(也就是不是第一个任务)
// 3.需要移动到顶部
if (curTop != null
&& (curTop.task != intentActivity.task || curTop.task != focusStack.topTask())
&& !mAvoidMoveToFront) {
mStartActivity.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
// 源Activity不存在或者源Activity所在栈顶部Activity存在并且顶部Activity和源Activity不在同一个任务中
if (mSourceRecord == null || (mSourceStack.topActivity() != null &&
mSourceStack.topActivity().task == mSourceRecord.task)) {
...
// 是否创建新任务并且清理该任务中的其他Activity
final boolean willClearTask =
(mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
== (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
if (!willClearTask) {// 不清理
// 获取启动栈
final ActivityStack launchStack = getLaunchStack(
mStartActivity, mLaunchFlags, mStartActivity.task, mOptions);
// 如果启动栈不存在,或者启动栈不是目标栈
if (launchStack == null || launchStack == mTargetStack) {
// We only want to move to the front, if we aren't going to launch on a
// different stack. If we launch on a different stack, we will put the
// task on top there.
// 把目标栈移动到前台
mTargetStack.moveTaskToFrontLocked(
intentActivity.task, mNoAnimation, mOptions,
mStartActivity.appTimeTracker, "bringingFoundTaskToFront");
mMovedToFront = true;// 标记
} else if (launchStack.mStackId == DOCKED_STACK_ID
|| launchStack.mStackId == FULLSCREEN_WORKSPACE_STACK_ID) {
// 如果是分屏模式,被启动的Activity会显示到启动它的Activity所在屏幕上
if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
mSupervisor.moveTaskToStackLocked(intentActivity.task.taskId,
launchStack.mStackId, ON_TOP, FORCE_FOCUS, "launchToSide",
ANIMATE);
} else {// 不是分屏模式
mTargetStack.moveTaskToFrontLocked(intentActivity.task, mNoAnimation,
mOptions, mStartActivity.appTimeTracker,
"bringToFrontInsteadOfAdjacentLaunch");
}
...
}
}
...
return intentActivity;
}
这里相对操作复杂,就是如果满足上面三个条件,就要将目标任务移动到前台来,这里调用了两个方法:mTargetStack.moveTaskToFrontLocked和mSupervisor.moveTaskToStackLocked。我们先看第一个:
Step53.ActivityStack.moveTaskToFrontLocked
final void moveTaskToFrontLocked(TaskRecord tr, boolean noAnimation, ActivityOptions options,
AppTimeTracker timeTracker, String reason) {
...
insertTaskAtTop(tr, null);
...
addRecentActivityLocked(top);
...
// Set focus to the top running activity of this stack.
ActivityRecord r = topRunningActivityLocked();
mService.setFocusedActivityLocked(r, reason);
...
mStackSupervisor.resumeFocusedStackTopActivityLocked();
...
}
这里有几个操作:将任务插入到顶部,将最顶部的Activity描述对象放到最近任务的列表中,获取顶部运行的Activity并将其设置为聚焦Activity,我们一个一个分析。
Step54.ActivityStack.insertTaskAtTop
// 插入任务到顶部
private void insertTaskAtTop(TaskRecord task, ActivityRecord newActivity) {
boolean isLastTaskOverHome = false;
// If the moving task is over home stack, transfer(转移) its return type to next task
if (task.isOverHomeStack()) {// 当前任务不是普通应用任务
// 获取相同用户下当前任务的下一个任务
final TaskRecord nextTask = getNextTask(task);
if (nextTask != null) {// 存在下一个任务,
// 则将下一个任务返回任务的类型设置为插入任务的类型
nextTask.setTaskToReturnTo(task.getTaskToReturnTo());
} else {// 如果不存在,那么当前任务就是最后一个了
isLastTaskOverHome = true;
}
}
// If this is being moved to the top by another activity or being launched from the home
// activity, set mTaskToReturnTo accordingly(相应的).
if (isOnHomeDisplay()) {// 默认显示屏
// 获取上一个有焦点的栈管理
ActivityStack lastStack = mStackSupervisor.getLastStack();
final boolean fromHome = lastStack.isHomeStack();
if (!isHomeStack() && (fromHome || topTask() != task)) {
// If it's a last task over home - we default to keep its return to type not to
// make underlying task focused when this one will be finished.
int returnToType = isLastTaskOverHome
? task.getTaskToReturnTo() : APPLICATION_ACTIVITY_TYPE;
if (fromHome && StackId.allowTopTaskToReturnHome(mStackId)) {
returnToType = lastStack.topTask() == null
? HOME_ACTIVITY_TYPE : lastStack.topTask().taskType;
}
task.setTaskToReturnTo(returnToType);
}
} else {
task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
}
// 从历史任务中移除该任务
mTaskHistory.remove(task);
// Now put task at top.插入任务到顶部
int taskNdx = mTaskHistory.size();
// 判断是否显示
final boolean notShownWhenLocked =
(newActivity != null && (newActivity.info.flags & FLAG_SHOW_FOR_ALL_USERS) == 0)
|| (newActivity == null && task.topRunningActivityLocked() == null);
// 如果插入任务不是当前用户的任务,并且也不进行显示
if (!mStackSupervisor.isCurrentProfileLocked(task.userId) && notShownWhenLocked) {
// Put non-current user tasks below current user tasks.
// 这里说明插入的任务不是当前用户的任务,那么从顶部向下查找,一直找到第一不是当前用户的任务的位置,
while (--taskNdx >= 0) {
final TaskRecord tmpTask = mTaskHistory.get(taskNdx);
if (!mStackSupervisor.isCurrentProfileLocked(tmpTask.userId)
|| tmpTask.topRunningActivityLocked() == null) {
break;
}
}
// 如果插入的任务不是当前用户的,那么就将该非当前用户任务插入到当前用户的任务下面并且在不是当前用户
// 的任务上面,也就是如果插入任务不是当前用户的那么就要将该任务插入到当前用户任务和非当前用户任务中间
++taskNdx;
}
// 插入任务
mTaskHistory.add(taskNdx, task);
updateTaskMovement(task, true);
}
这里面主要是要考虑插入的任务是不是当前用户的任务,如果不是要依次查找非当前用户任务位置,然后将其放置到非当前用户任务的顶部位置。55步是将其添加到最近任务记录中。56步是获取顶部运行的Activity的描述对象。
Step57.ActivityManagerService.setFocusedActivityLocked
boolean setFocusedActivityLocked(ActivityRecord r, String reason) {
...
// 将要启动的Activity移动到前台
if (mStackSupervisor.moveActivityStackToFront(r, reason + " setFocusedActivity")) {
mWindowManager.setFocusedApp(r.appToken, true);
}
...
return true;
}
这里主要是通过调用ActivityStackSupervisor.moveActivityStackToFront方法移动焦点到新的Activity。
Step58.ActivityStackSupervisor.moveActivityStackToFront
// 将要启动的Activity移动到前台
boolean moveActivityStackToFront(ActivityRecord r, String reason) {
...
// 将任务移动到前台
task.stack.moveToFront(reason, task);
return true;
}
Step59.ActivityStack.moveToFront
void moveToFront(String reason, TaskRecord task) {
...
mStackSupervisor.setFocusStackUnchecked(reason, this);
...
insertTaskAtTop(task, null);
...
}
将任务移动到顶部,方法讲过了看上面的代码分析。
Step60.ActivityStackSupervisor.resumeFocusedStackTopActivityLocked
boolean resumeFocusedStackTopActivityLocked() {
return resumeFocusedStackTopActivityLocked(null, null, null);
}
Step61.ActivityStackSupervisor.resumeFocusedStackTopActivityLocked
boolean resumeFocusedStackTopActivityLocked(
ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
if (targetStack != null && isFocusedStack(targetStack)) {// 如果目标栈存在并且处于聚焦状态,直接启动
return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
}
// 如果目标栈不存在或者没有在聚焦状态,则从聚焦栈中取出栈顶的Activity
final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
if (r == null || r.state != RESUMED) {
mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
}
return false;
}
Step62.ActivityStack.resumeTopActivityUncheckedLocked
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
...
result = resumeTopActivityInnerLocked(prev, options);
...
}
最终调用resumeTopActivityInnerLocked方法来进行处理,这个比较复杂,我们放到第二部分分析。我们回到前面接着分析。
Step63.ActivityStackSupervisor.moveTaskToStackLocked
boolean moveTaskToStackLocked(int taskId, int stackId, boolean toTop, boolean forceFocus,
String reason, boolean animate) {
return moveTaskToStackLocked(taskId, stackId, toTop, forceFocus, reason, animate,
false /* deferResume */);
}
Step64.ActivityStackSupervisor.moveTaskToStackLocked
boolean moveTaskToStackLocked(int taskId, int stackId, boolean toTop, boolean forceFocus,
String reason, boolean animate, boolean deferResume) {
// 根据id获取Task描述对象TaskRecord
final TaskRecord task = anyTaskForIdLocked(taskId);
...
resumeFocusedStackTopActivityLocked();
...
}
第一个方法我们前面已经分析过了,这里不再提,第二个方法我们上面Step60已经分析过了。
Step65.ActivityStarter.resumeTargetStackIfNeeded
// 恢复目标栈
private void resumeTargetStackIfNeeded() {
...
mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, null, mOptions);
...
}
这里就是上面64中的方法也就是60步。
Step66.ActivityStarter.setTaskFromIntentActivity
这个方法主要是目标ActivityRecord对象中获取task。代码不多,可以自己看看。
Step68.ActivityStarter.setTaskFromReuseOrCreateNewTask
private void setTaskFromReuseOrCreateNewTask(TaskRecord taskToAffiliate) {
mTargetStack = computeStackFocus(mStartActivity, true, mLaunchBounds, mLaunchFlags,
mOptions);
if (mReuseTask == null) {// 没有可用任务
// 创建新的任务并插入栈中
final TaskRecord task = mTargetStack.createTaskRecord(
mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
mNewTaskIntent != null ? mNewTaskIntent : mIntent,
mVoiceSession, mVoiceInteractor, !mLaunchTaskBehind /* toTop */);
mStartActivity.setTask(task, taskToAffiliate);
...
} else {
mStartActivity.setTask(mReuseTask, taskToAffiliate);
}
}
如果没有可复用的任务就需要创建新的任务,并且添加,如果有就直接添加。
Step71.ActivityStack.startActivityLocked
// 启动Activity(Locked表示线程安全的)
final void startActivityLocked(ActivityRecord r, boolean newTask, boolean keepCurTransition,
ActivityOptions options) {
TaskRecord rTask = r.task;
final int taskId = rTask.taskId;
// mLaunchTaskBehind tasks get placed at the back of the task stack.
if (!r.mLaunchTaskBehind && (taskForIdLocked(taskId) == null || newTask)) {
// Last activity in task had been removed or ActivityManagerService is reusing task.
// Insert or replace.
// Might not even be in.
// task中的上一个activity已被移除,或者AMS重用该task,则将该task移到顶部
insertTaskAtTop(rTask, r);
mWindowManager.moveTaskToTop(taskId);
}
// 将目标Activity放到栈顶
task.addActivityToTop(r);
task.setFrontOfTask();
...
}
这里就是将Activity放到栈顶,然后显示。
Step72.ActivityStack.addRecentActivityLocked
这个方法在55步分析过不再分析。
这里是第一部分的,因此启动过程很复杂所以时序图很多,只能分两部分来讲,很多的代码没有分析,需要的可以去忘得coding拉取代码来看,里面有注释。
第二部分:
ActivityStart2.jpg这一部分是上面过程的中间一段过程,由于东西比较多,时序图没法画了,所以提取出来单独分析,主要是ActivityStack.resumeTopActivityInnerLocked方法。
Step1.ActivityStack.resumeTopActivityInnerLocked
/**
* 1.当找不到需要resume的Activity,则直接回到桌面;
* 2.否则,当mResumedActivity不为空,则执行startPausingLocked()暂停该activity;
* 3.然后再进入startSpecificActivityLocked环节。
*
* @param prev 源Activity对象
* @param options
*
* @return
*/
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
...
// Find the first activity that is not finishing.
// 前面我们把要启动的Activity放置在当前Activity组件堆栈的顶端,并且它是正在等待启动的,即它不是
// 处于结束状态的,因此next就指向了我们将要启动的Activity组件
final ActivityRecord next = topRunningActivityLocked();
// Remember how we'll process this pause/resume situation, and ensure
// that the state is reset however we wind up proceeding.
// 将mUserLeaving放置在userLeaving中,并且重置mUserLeaving为false,因此就可以通过userLeaving
// 判断是否需要向源Activity组件发送一个用户离开的时间通知了
final boolean userLeaving = mStackSupervisor.mUserLeaving;
mStackSupervisor.mUserLeaving = false;
final TaskRecord prevTask = prev != null ? prev.task : null;
if (next == null) {// 如果要启动的Activity为空,因为我们有要启动的Activity,因此不走这里
...
if (!mFullscreen && adjustFocusToNextFocusableStackLocked(returnTaskType, reason)) {
// Try to move focus to the next visible stack with a running activity if this
// stack is not covering the entire screen.
return mStackSupervisor.resumeFocusedStackTopActivityLocked(
mStackSupervisor.getFocusedStack(), prev, null);
}
...
// 暂停其他Activity
boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, next, dontWaitForPause);
// 我们从一个Activity启动另一个Activity的时候,源Activity不是空,mResumedActivity指向源Activity,
// 因此mResumedActivity不为空
if (mResumedActivity != null) {
if (DEBUG_STATES) Slog.d(TAG_STATES,
"resumeTopActivityLocked: Pausing " + mResumedActivity);
// 检测是否正在终止一个Activity组件,如果是,那么要等到它中止完成之后再启动Activity组件next
pausing |= startPausingLocked(userLeaving, false, next, dontWaitForPause);
}
...
// If the most recent activity was noHistory but was only stopped rather
// than stopped+finished because the device went to sleep, we need to make
// sure to finish it as we're making a new activity topmost.
if (mService.isSleepingLocked() && mLastNoHistoryActivity != null &&
!mLastNoHistoryActivity.finishing) {
...
requestFinishActivityLocked(mLastNoHistoryActivity.appToken, Activity.RESULT_CANCELED,
null, "resume-no-history", false);
...
}
...
// 调用onActivityResult函数
next.app.thread.scheduleSendResult(next.appToken, a);
...
next.app.thread.scheduleNewIntent(
next.newIntents, next.appToken, false /* andPause */);
...
// 触发onResume()
next.app.thread.scheduleResumeActivity(next.appToken, next.app.repProcState,
mService.isNextTransitionForward(), resumeAnimOptions);
...
mStackSupervisor.startSpecificActivityLocked(next, true, false);
...
requestFinishActivityLocked(next.appToken, Activity.RESULT_CANCELED, null,
"resume-exception", true);
...
// 目标Activity没有启动会调用startSpecificActivityLocked来启动Activity
mStackSupervisor.startSpecificActivityLocked(next, true, true);
}
...
return true;
}
这个函数代码量很大,我只留下了核心的一些来分析,其他的可以对照源码进行分析。
Step2.ActivityStack.adjustFocusToNextFocusableStackLocked
private boolean adjustFocusToNextFocusableStackLocked(int taskToReturnTo, String reason) {
final ActivityStack stack = getNextFocusableStackLocked();// 获取下一个有焦点的栈
final String myReason = reason + " adjustFocusToNextFocusableStack";
if (stack == null) {// 没有能获取焦点的栈了
return false;
}
// 获取有焦点的顶部运行的Activity对象
final ActivityRecord top = stack.topRunningActivityLocked();
// 如果顶部stack是Launcher或者最近任务所在的stack,并且存在该Activity,并且该Activity没有显示
if (stack.isHomeStack() && (top == null || !top.visible)) {
// 那么要显示Launcher或者最近任务
return mStackSupervisor.moveHomeStackTaskToTop(taskToReturnTo, reason);
}
return mService.setFocusedActivityLocked(top, myReason);
}
这里是获取下一个能够获取焦点的栈,比如最近任务或者Launcher,如果获取不到返回false,如果存在,那么获取该栈的顶部Activity,如果是HomeStack也就是Launcher栈或者最近任务栈,并且顶部Activity没有显示或者不存在则显示Launcher或者最近任务界面。否则设置到AMS中作为焦点Activity,这个函数我们讲过了。
步骤3里的函数我们也分析过了,这里也不再分析,我们开始分析第四步。
Step4.ActivityStackSupervisor.pauseBackStacks
boolean pauseBackStacks(boolean userLeaving, ActivityRecord resuming, boolean dontWait) {
boolean someActivityPaused = false;
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
...
someActivityPaused |= stack.startPausingLocked(userLeaving, false, resuming,
dontWait);
...
}
}
return someActivityPaused;
}
通过for循环暂停所有后台栈中的Activity
Step5.ActivityStack.startPausingLocked
final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping,
ActivityRecord resuming, boolean dontWait) {
if (mPausingActivity != null) {
...
completePauseLocked(false, resuming);
...
}
如果需要暂停的Activity不为空,那么要完成暂停操作。
Step6.ActivityStack.completePauseLocked
private void completePauseLocked(boolean resumeNext, ActivityRecord resuming) {
ActivityRecord prev = mPausingActivity;
// 在前面我们将mPausingActivity指向了与源Activity组件对应的ActivityRecord对象,此处为true
if (prev != null) {
// 表示源Activity状态已经是Paused状态了
prev.state = ActivityState.PAUSED;
if (prev.finishing) {// 如果是正在结束
prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE, false);
} else if (prev.app != null) {// 进程还存在
...
if (prev.deferRelaunchUntilPaused) {
// Complete the deferred relaunch that was waiting for pause to complete.
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Re-launching after pause: " + prev);
relaunchActivityLocked(prev, prev.configChangeFlags, false,
prev.preserveWindowOnDeferredRelaunch);
}
...
}
...
}
...
}
finish的过程我们下一章再分析,我们下面分析一个核心的函数relaunchActivityLocked,由于下面会涉及Activity的启动,因此我们通过这个函数直接来分析。
Step7.ActivityStack.relaunchActivityLocked
private void relaunchActivityLocked(
ActivityRecord r, int changes, boolean andResume, boolean preserveWindow) {
...
r.app.thread.scheduleRelaunchActivity(r.appToken, results, newIntents, changes,
!andResume, new Configuration(mService.mConfiguration),
new Configuration(r.task.mOverrideConfig), preserveWindow);
...
}
看到什么代码应该很熟悉了,调用ApplicationThreadProxy.scheduleRelaunchActivity方法然后通过Binder调用ApplicationThread.scheduleRelaunchActivity函数。我这里的图就省略了中间的过程。但是要知道这个过程。
Step8.ApplicationThread.scheduleRelaunchActivity
public final void scheduleRelaunchActivity(IBinder token,
List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
int configChanges, boolean notResumed, Configuration config,
Configuration overrideConfig, boolean preserveWindow) {
requestRelaunchActivity(token, pendingResults, pendingNewIntents,
configChanges, notResumed, config, overrideConfig, true, preserveWindow);
}
Step9.ActivityThread.requestRelaunchActivity
public final void requestRelaunchActivity(IBinder token,
List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
int configChanges, boolean notResumed, Configuration config,
Configuration overrideConfig, boolean fromServer, boolean preserveWindow) {
...
sendMessage(H.RELAUNCH_ACTIVITY, target);
...
}
这个过程应该很熟悉了,所以这里不再多解释。后面就直接分析过程了。这里回到ActivityThread.H的handleMessage方法中,然后调用ActivityThread.handleRelaunchActivity方法。
Step10.ActivityThread.handleRelaunchActivity
private void handleRelaunchActivity(ActivityClientRecord tmp) {
...
// Need to ensure state is saved.
if (!r.paused) {
performPauseActivity(r.token, false, r.isPreHoneycomb(), "handleRelaunchActivity");
}
if (r.state == null && !r.stopped && !r.isPreHoneycomb()) {
callCallActivityOnSaveInstanceState(r);
}
handleDestroyActivity(r.token, false, configChanges, true);
...
handleLaunchActivity(r, currentIntent, "handleRelaunchActivity");
...
}
这里performPauseActivity会根据12-17步一直执行到Activity.onPause方法。
callCallActivityOnSaveInstanceState方法会执行18-21步骤最终执行Activity.onSaveInstanceState方法。
handleDestroyActivity方法会执行到Activity.onDestroy方法。
这些过程都很简单跟着代码走一下就都知道了,过程基本相同。
Step23.ActivityThread.handleLaunchActivity
// 启动Activity
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
...
// Make sure we are running with the most recent config.
// 最终回调目标Activity的onConfigurationChanged()
handleConfigurationChanged(null, null);
...
// 首先调用performLaunchActivity方法将目标Activity组件启动起来,最终调用目标Activity的onCreate方法
Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
...
// 最终回调目标Activity的onStart,onResume.
handleResumeActivity(r.token, false, r.isForward,
!r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
if (!r.activity.mFinished && r.startsNotResumed) {
...
performPauseActivityIfNeeded(r, reason);
...
} else {
...
}
}
上面代码中handleConfigurationChanged方法最终会调用Activity.onConfigurationChanged方法。handleResumeActivity方法最终会调用Activity.onResume方法。最主要还是看performLaunchActivity方法。
Step28.ActivityThread.performLaunchActivity
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
...
Activity activity = null;
try {
// 将目标Activity的类文件加载到内存中,并创建一个实例。由于所有Activity组件都是从Activity类
// 继承下来的,因此,我们就可以将前面创建的Activity组件保存在Activity对象activity中
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
...
try {
// 创建Application对象
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
if (activity != null) {
...
// 使用ContextImpl对象appContext和ActivityClientRecord对象r来初始化Activity对象activity
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor, window);
...
int theme = r.activityInfo.getThemeResource();
if (theme != 0) {
activity.setTheme(theme);
}
activity.mCalled = false;
// 调用成员变量mInstrumentation的callActivityOnCreate方法将Activity对象activity启动起来,
// 会调用Activity的onCreate方法
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
...
if (!r.activity.mFinished) {
activity.performStart();
r.stopped = false;
}
if (!r.activity.mFinished) {
if (r.isPersistable()) {
if (r.state != null || r.persistentState != null) {
mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,
r.persistentState);
}
} else if (r.state != null) {
mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
}
}
...
}
...
return activity;
}
这个启动过程:
通过29步加载Activity,
然后通过31步创建Application,
在35步调用Application的onCreate方法,
37步调用Activity的attach方法,
38步设置主题,
39步调用Activity的onCreate方法,
42步调用Activity的onStart方法,
45步调用Activity的onRestoreInstanceState方法,
然后回到ActivityThread.handleLaunchActivity方法执行handleResumeActivity方法,也就是48步以后;
在调用onResume函数之前可能会先调用onNewIntent方法和onActivityResult方法,这样一来onResume函数之前的一个流程基本就出来了,由于代码比较简单,这里不再贴代码,自己跟着这个流程自己看看就知道了。
再看65步到67步,这个是从外面调用onActivityResult、onNewIntent和onResume方法的和第一部分的8-15步一样,可以参考前面的就好了。
最后68-70步其实还是会执行到handleLaunchActivity方法上来,所以这里就不再分析。
从整篇文章看,Activity的启动流程是非常复杂,可以说在四大组件中是最复杂的,但是里面很多过程是相同的,比如生命周期的每个方法的调用过程基本是一样的,因此看书谷歌工程师设计的巧妙,这样也有助于我们对于源码的学习,减少了我们对于源码的分析过程,博客写了很多,但是对于整个过程来说还是很多地方没有分析,想了解完整的过程的可以下载我的代码,里面有很全面的注释,然后自己对着上面的时序图来进行分析,过几遍也就熟悉了,我写这片博客也用了很长的时间,主要是中间总是有事,写写停停,时序图更改了好几次。中间也有一些问题,不过跟着源码走还是都能找到的。
代码地址:
直接拉取导入开发工具(Intellij idea或者Android studio)
https://git.coding.net/codemx/Android-25.git
注
首发地址:http://www.codemx.cn
Android开发群:192508518
微信公众账号:Code-MX
注:本文原创,转载请注明出处,多谢。