转载来源:
(一)Activity生命周期管理
1. 前言
AMS(ActivityManagerService)是Activity管理的核心组件,提供了Activity的启动、生命周期管理、栈管理等功能,熟悉AMS会对我们认识Activity的工作原理有很大的帮助。当前比较成熟的插件化技术,也是通过对Activity启动流程中的重要组件(如Instrumentation或主线程Handler等)进行Hook完成的,掌握AMS对我们学习插件化技术也有很大的帮助
AMS中内容很多,对它的分析也不可能面面俱到,我期望从Activity的启动、Activity消息回传(onActivityResult)、Activity栈管理、AMS与WMS和PMS的协同工作方面入手,希望本系列文章完成后可以对AMS有一个更新的认识
2. Activity的生命周期
2.1. 一个Activity从启动到销毁所经历的周期
onCreate -> onStart -> onResume -> onPause -> onStop -> onDestory
这属于Android最基础的知识,就不再赘述了
2.2. 从一个Activity启动另一个Activity的生命周期
现在有两个Activity,分别是AActivity和BActivity,如果从AActivity跳转到BActivity,那么它们的生命周期会是下面这个样子:
AActivity#onPause -> BActivity#onCreate -> BActivity#onStart -> BActivity#onResume -> AActivity#onStop
如下图:
而从BActivity返回时,它们的生命周期是这样的:
BActivity#onPause -> AActivity#onStart -> AActivity#onResume -> BActivity#onStop -> BActivity#onDestroy
为什么是这样呢?下面我们从源码的角度去分析一下
3.源码分析
在做源码分析之前,我们要先理解两个概念
- Android Binder IPC机制
- Hander idleHandler机制
3.1. Binder
Binder是Android跨进程通信的核心,但不是本文的重点,这里不多做讲解,感兴趣的朋友可以看一下我之前写过的Binder系列文章:Binder系列
在本篇文章中,我们只需要知道每当看到类似mRemote.transact
这种调用时,既是跨进程通信的开始
3.2. IdleHandler
当消息队列空闲时会执行IdelHandler的queueIdle()
方法,该方法返回一个boolean值,
如果为false则执行完毕之后移除这条消息,
如果为true则保留,等到下次空闲时会再次执行
也就是说,IdleHandler是Handler机制中MessageQueue空闲时才会执行的一种特殊Handler
3.3. Activity在AMS中的标识
每一个Activity实例在AMS中都会对应一个ActivityRecord,ActivityRecord对象是在Activity启动过程中创建的,每个ActivityRecord中又会有一个ProcessRecord标记Activity所在的进程
而在APP进程中,在Activity启动时,也会创建一个ActivityClientRecord,与AMS中的ActivityRecord遥相呼应。
Activity、ActivityClientRecord、ActivityRecord互相联系的纽带是一个token对象,它继承于IApplicationToken.Stub,这是一个Binder对象,在Activity、ActivityClientRecord、ActivityRecord中均有一份。
Activity、ActivityClientRecord、ActivityRecord之间的关系图大致如下—注意区分所在进程:
3.4. 启动过程时序图
黄色为APP进程,蓝色为AMS进程
3.5. 从AActivity跳转BActivity的生命周期分析
AMS的逻辑太多,本文只针对Activity声明周期相关的代码,其他相关逻辑后面几篇文章继续分析
从Activity开始
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
@Nullable Bundle options) {
if (mParent == null) {
options = transferSpringboardActivityOptions(options);
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
} else {
}
}
Instrumentation#execStartActivity方法:
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
...
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess(who);
int result = ActivityManager.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;
}
重要入参及含义:
- who: 启动源Activity
- contextThread : 宿主Activity的ApplicationThread
- token:Activity的身份标识 -> Activity#mToken -> ActivityClientRecord#token -> ActivityRecord#appToken -> IApplicationToken.Stub
- target: 哪个activity调用的start方法,因此这个Activity会接收任何的返回结果,如果start调用不是从Activity中发起的则有可能为null
- intent: 启动Activity时的intent
- requestCoode: 启动Activity时的requestCode
- options: 启动Activity的选项
注意token参数,本文将重点追踪它的变化,这个参数非常重要,后面会有很多地方用到
继续走逻辑,在这里进行了IPC调用,从APP进程转入AMS进程执行,ActivityManager.getService() .startActivity
调用在AMS进程对应的是ActivityManagerService#startActivity,我们看一下
ActivityManagerService#startActivity经过一系列的调用后,会走到ActivityStarter#startActivityMayWait
final int startActivityMayWait(IApplicationThread caller, int callingUid,
int requestRealCallingPid, int requestRealCallingUid,
String callingPackage, Intent intent, String resolvedType,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
IBinder resultTo, String resultWho, int requestCode, int startFlags,
ProfilerInfo profilerInfo, WaitResult outResult,
Configuration globalConfig, Bundle bOptions, boolean ignoreTargetSecurity, int userId,
TaskRecord inTask, String reason) {
...
// Collect information about the target of the Intent.
// zhangyulong 解析Intent中的Activity信息
ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
...
// zhangyulong 声明一个ActivityRecord数组
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, inTask,
reason);
Binder.restoreCallingIdentity(origId);
...
return res;
}
}
这里进行的工作是解析Intent信息,并继续调用startActivityLocked
,注意入参中的resultTo就是从App进程传入的token,依旧是透传给startActivityLocked
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, TaskRecord inTask, String reason) {
if (TextUtils.isEmpty(reason)) {
throw new IllegalArgumentException("Need to specify a reason.");
}
mLastStartReason = reason;
mLastStartActivityTimeMs = System.currentTimeMillis();
mLastStartActivityRecord[0] = null;
mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,
aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,
callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,
inTask);
if (outActivity != null) {
// mLastStartActivityRecord[0] is set in the call to startActivity above.
outActivity[0] = mLastStartActivityRecord[0];
}
// Aborted results are treated as successes externally, but we must track them internally.
return mLastStartActivityResult != START_ABORTED ? mLastStartActivityResult : START_SUCCESS;
}
这个方法也没做太多事情,将参数透传给startActivity
继续执行
private int startActivity(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, TaskRecord inTask) {
int err = ActivityManager.START_SUCCESS;
// Pull the optional Ephemeral Installer-only bundle out of the options early.
final Bundle verificationBundle
= options != null ? options.popAppVerificationBundle() : null;
ProcessRecord callerApp = null;
if (caller != null) {
callerApp = mService.getRecordForAppLocked(caller);
if (callerApp != null) {
callingPid = callerApp.pid;
callingUid = callerApp.info.uid;
} else {
Slog.w(TAG, "Unable to find app for caller " + caller
+ " (pid=" + callingPid + ") when starting: "
+ intent.toString());
err = ActivityManager.START_PERMISSION_DENIED;
}
}
final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
if (err == ActivityManager.START_SUCCESS) {
Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
+ "} from uid " + callingUid);
}
ActivityRecord sourceRecord = null;
ActivityRecord resultRecord = null;
if (resultTo != null) {
// 通过resultTo在寻找记录在AMS中记录的ActivityRecord,这个ActivityRecord和启动Activity的源Activity对应
sourceRecord = mSupervisor.isInAnyStackLocked(resultTo);
if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
"Will send result to " + resultTo + " " + sourceRecord);
if (sourceRecord != null) {
if (requestCode >= 0 && !sourceRecord.finishing) {
resultRecord = sourceRecord;
}
}
}
final int launchFlags = intent.getFlags();
// 新建一条目标Activity的ActivityRecord,这条ActivityRecord和即将打开的Activity实例对应
ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
mSupervisor, options, sourceRecord);
if (outActivity != null) {
outActivity[0] = r;
}
return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true,
options, inTask, outActivity);
}
记的我们在分析源码之前所画的ActivityRecord、ActivityClientRecord、Activity之间的关系图么?这里就派上用场了,入参resultTo就是启动Activity时传递的token,那么,在AMS中,必然会有一条ActivityRecord与之对应,通过mSupervisor.isInAnyStackLocked(resultTo)
找到与AActivity对应的ActivityRecord。
这个方法还有一个重要的任务就是新建一条ActivityRecord记录,这条记录和即将打开的Activity,即BActivity对应。完成这些工作后,继续执行startActivity。
startActivity继续调用了startActivityUnchecked
,这个方法最重要的功能是对Acitivity栈和Activity启动模式进行处理,篇幅很长,逻辑复杂,但是不是本篇的重点,所以我们后面的文章再着重分析,现在只关注Activity启动流程相关的部分
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
ActivityRecord[] outActivity) {
...
if (mDoResume) {
final ActivityRecord topTaskActivity =
mStartActivity.getTask().topRunningActivityLocked();
if (!mTargetStack.isFocusable()
|| (topTaskActivity != null && topTaskActivity.mTaskOverlay
&& mStartActivity != topTaskActivity)) {
mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
mWindowManager.executeAppTransition();
} else {
if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {
mTargetStack.moveToFront("startActivityUnchecked");
}
mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
mOptions);
}
} else {
mTargetStack.addRecentActivityLocked(mStartActivity);
}
...
return START_SUCCESS;
}
3.5.1. AActivity#onPause
注意看mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity, mOptions)
,这里,mStartActivity是即将启动的ActivityRecord,mTargetStack是在本方法中计算得到的它所在的ActivityStack,继续看resumeFocusedStackTopActivityLocked
还记得在开篇时讲到的从AActivity跳转到BActivity的生命周期过程么?不记得没关系,复习一下先:
AActivity#onPause -> BActivity#onCreate -> BActivity#onStart -> BActivity#onResume -> AActivity#onStop,
在resumeFocusedStackTopActivityLocked
这个方法我们将接触到这个过程中的第一个声明周期方法,即AActivity#onPause,而且本身这个方法的调用过程也特别复杂,需要重点解析一下,先看一下代码:
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
if (!mService.mBooting && !mService.mBooted) {
// Not ready yet!
return false;
}
// Find the next top-most activity to resume in this stack that is not finishing and is
// focusable. If it is not focusable, we will fall into the case below to resume the
// top activity in the next focusable task.
// 获取栈顶正在聚焦的Activity
final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);
final boolean hasRunningActivity = next != null;
// TODO: Maybe this entire condition can get removed?
if (hasRunningActivity && getDisplay() == null) {
// zhangyulong 异常情况,有正在运行的activity但getDisplay为空
return false;
}
mStackSupervisor.cancelInitializingActivities();
// Remember how we'll process this pause/resume situation, and ensure
// that the state is reset however we wind up proceeding.
final boolean userLeaving = mStackSupervisor.mUserLeaving;
mStackSupervisor.mUserLeaving = false;
if (!hasRunningActivity) {
// There are no activities left in the stack, let's look somewhere else.
// zhangyulong task 退干净了,恢复其他的task
return resumeTopActivityInNextFocusableStack(prev, options, "noMoreActivities");
}
next.delayedResume = false;
...
// Activity栈中有需要Pause操作的Activity
boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, next, false);
if (mResumedActivity != null) {
// 暂停当前正在显示的Activity
pausing |= startPausingLocked(userLeaving, false, next, false);
}
if (pausing && !resumeWhilePausing) {
if (next.app != null && next.app.thread != null) {
mService.updateLruProcessLocked(next.app, true, null);
}
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return true;
}
...
ActivityStack lastStack = mStackSupervisor.getLastStack();
if (next.app != null && next.app.thread != null) {
...
} else {
// Whoops, need to restart this activity!
if (!next.hasBeenLaunched) {
next.hasBeenLaunched = true;
} else {
if (SHOW_APP_STARTING_PREVIEW) {
next.showStartingWindow(null /* prev */, false /* newTask */,
false /* taskSwich */);
}
if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Restarting: " + next);
}
if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Restarting " + next);
mStackSupervisor.startSpecificActivityLocked(next, true, true);
}
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return true;
}
这个方法会执行两次,第一次进入时,final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);
获取到的是栈顶焦点Activity,在执行该方法之前,我们已经将目标ActivityRecord入栈,因此,这里获取的是要打开的目标ActivityRecord,mStackSupervisor.pauseBackStacks(userLeaving, next, false);
是判断ActivityStack中是否有需要pause的Activity,如果有,说明还有活动的Activity没有Pause,我们要先执行Pause操作,通过执行startPausingLocked(userLeaving, false, next, false);
将当前未Pause的Activity进行Pause,在执行完毕后方法直接return了。先进去看一下startPausingLocked
:
final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping,
ActivityRecord resuming, boolean pauseImmediately) {
// 将mResumedActivity赋值prev,并将mResumedActivity置空
ActivityRecord prev = mResumedActivity;
mResumedActivity = null;
mPausingActivity = prev;
if (prev.app != null && prev.app.thread != null) {
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending pause: " + prev);
try {
EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
prev.userId, System.identityHashCode(prev),
prev.shortComponentName);
mService.updateUsageStats(prev, false);
// 开始进行Pause操作
prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
userLeaving, prev.configChangeFlags, pauseImmediately);
} catch (Exception e) {
// Ignore exception, if process died other code will cleanup.
Slog.w(TAG, "Exception thrown during pause", e);
mPausingActivity = null;
mLastPausedActivity = null;
mLastNoHistoryActivity = null;
}
} else {
mPausingActivity = null;
mLastPausedActivity = null;
mLastNoHistoryActivity = null;
}
if (mPausingActivity != null) {
if (!uiSleeping) {
prev.pauseKeyDispatchingLocked();
} else if (DEBUG_PAUSE) {
Slog.v(TAG_PAUSE, "Key dispatch not paused for screen off");
}
if (pauseImmediately) {
completePauseLocked(false, resuming);
return false;
} else {
// 延时500ms处理pause后续操作
schedulePauseTimeout(prev);
return true;
}
} else {
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Activity not running, resuming next.");
if (resuming == null) {
mStackSupervisor.resumeFocusedStackTopActivityLocked();
}
return false;
}
}
mResumedActivity就是将被Pause的Activity,通过prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing, userLeaving, prev.configChangeFlags, pauseImmediately);
对其进行Pause,这里实际是一个异步操作,因此,在方法的末端,添加了一个500ms的延时消息防止Pause操作timeout,当然,这个延时消息不一定会执行,如果pause操作在500ms以内完成会将这个消息取消。如果熟悉Activity启动流程的话,我们就会知道schedulePauseActivity
最终一定会执行到ApplicationThread#handlePauseActivity,这个ApplicationThread在本文章的场景中是AActivity的ApplicationThread,看下代码:
private void handlePauseActivity(IBinder token, boolean finished,
boolean userLeaving, int configChanges, boolean dontReport, int seq) {
ActivityClientRecord r = mActivities.get(token);
if (DEBUG_ORDER) Slog.d(TAG, "handlePauseActivity " + r + ", seq: " + seq);
if (!checkAndUpdateLifecycleSeq(seq, r, "pauseActivity")) {
return;
}
if (r != null) {
//Slog.v(TAG, "userLeaving=" + userLeaving + " handling pause of " + r);
if (userLeaving) {
performUserLeavingActivity(r);
}
r.activity.mConfigChangeFlags |= configChanges;
// 真正调用Activity#onPause
performPauseActivity(token, finished, r.isPreHoneycomb(), "handlePauseActivity");
// Make sure any pending writes are now committed.
if (r.isPreHoneycomb()) {
QueuedWork.waitToFinish();
}
// Tell the activity manager we have paused.
if (!dontReport) {
try {
// 通知AMS Activity已完成Pause
ActivityManager.getService().activityPaused(token);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
mSomeActivitiesChanged = true;
}
}
其中,performPauseActivity最终会调用AActivity的onPause,继续向下执行会通过ActivityManager.getService().activityPaused(token)
通知AMS进程Activity已完成Pause,
// ActivityManagerService
public final void activityPaused(IBinder token) {
final long origId = Binder.clearCallingIdentity();
synchronized(this) {
ActivityStack stack = ActivityRecord.getStackLocked(token);
if (stack != null) {
stack.activityPausedLocked(token, false);
}
}
Binder.restoreCallingIdentity(origId);
}
继续看ActivityStack#activityPausedLocked
final void activityPausedLocked(IBinder token, boolean timeout) {
...
final ActivityRecord r = isInStackLocked(token);
if (r != null) {
// 取消Pause的延时等待消息消息
mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
if (mPausingActivity == r) {
if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to PAUSED: " + r
+ (timeout ? " (due to timeout)" : " (pause complete)"));
mService.mWindowManager.deferSurfaceLayout();
try {
// 完成Pause的后续操作
completePauseLocked(true /* resumeNext */, null /* resumingActivity */);
} finally {
mService.mWindowManager.continueSurfaceLayout();
}
return;
}
....
}
比较重要的两个操作:
- 取消Pause的延时等待消息消息
- 完成Pause的后续操作
完成Pause后续操作是在ActivityStack#completePauseLocked中
private void completePauseLocked(boolean resumeNext, ActivityRecord resuming) {
ActivityRecord prev = mPausingActivity;
...
if (prev != null) {
...
// 将已被Pause的Activity加入到mStackSupervisor.mStoppingActivities列表中
addToStopping(prev, true /* scheduleIdle */, false /* idleDelayed */);
...
}
if (resumeNext) {
final ActivityStack topStack = mStackSupervisor.getFocusedStack();
if (!topStack.shouldSleepOrShutDownActivities()) {
// Resume栈顶Activity, prev是当前在pause的
mStackSupervisor.resumeFocusedStackTopActivityLocked(topStack, prev, null);
} else {
checkReadyForSleep();
ActivityRecord top = topStack.topRunningActivityLocked();
if (top == null || (prev != null && top != prev)) {
mStackSupervisor.resumeFocusedStackTopActivityLocked();
}
}
}
...
}
重点关注mStackSupervisor.resumeFocusedStackTopActivityLocked(topStack, prev, null);
兜兜转转,又回到了原点,我们即将第二次调用ActivityStack#resumeTopActivityInnerLocked,这次跟上一次又有所不同,因为已经完成活跃Activity的pause,因此,判断是否需要Pause的分支语句就不会执行,继续向下执行到mStackSupervisor.startSpecificActivityLocked(next, true, true);
,这个方法还有一个重要的事情就是将已被Pause的Activity加入到mStackSupervisor.mStoppingActivities
的列表中,这是一个ArrayList,至于什么时候用,后面会讲到
3.5.2. BActivity#onCreate
讲到这里,我们只是刚完成了AActivity的Pause,有些朋友肯定已经着急了,那得分析到啥时候啊,快了快了,后面就很快了,加快进度,接着看ActivityStackSupervisor#startSpecificActivityLocked
void startSpecificActivityLocked(ActivityRecord r,
boolean andResume, boolean checkConfig) {
// 获取目标Activity的进程信息
ProcessRecord app = mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid, true);
r.getStack().setLaunchTime(r);
if (app != null && app.thread != null) {
try {
if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
|| !"android".equals(r.info.packageName)) {
app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
mService.mProcessStats);
}
// 启动Activity
realStartActivityLocked(r, app, andResume, checkConfig);
return;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting activity "
+ r.intent.getComponent().flattenToShortString(), e);
}
// If a dead object exception was thrown -- fall through to
// restart the application.
}
// 如果没有进程信息则启动新的进程
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false, true);
}
这个方法的主要工作是给ActivityRecord分配进程,如果没有进程,则启动新的进程,从AActivity跳BActivity是同一个进程,因此会继续执行realStartActivityLocked(r, app, andResume, checkConfig):
final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
boolean andResume, boolean checkConfig) throws RemoteException {
...
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info,
...
return true;
}
方法比较长,掐头去尾只看app.thread.scheduleLaunchActivity
,从这里开始进入App进程执行,scheduleLaunchActivity
方法在APP进程对应的是ApplicationThread#scheduleLaunchActivity:
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
int procState, Bundle state, PersistableBundle persistentState,
List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {
updateProcessState(procState, false);
ActivityClientRecord r = new ActivityClientRecord();
r.token = token;
r.ident = ident;
r.intent = intent;
r.referrer = referrer;
r.voiceInteractor = voiceInteractor;
r.activityInfo = info;
r.compatInfo = compatInfo;
r.state = state;
r.persistentState = persistentState;
r.pendingResults = pendingResults;
r.pendingIntents = pendingNewIntents;
r.startsNotResumed = notResumed;
r.isForward = isForward;
r.profilerInfo = profilerInfo;
r.overrideConfig = overrideConfig;
updatePendingConfiguration(curConfig);
sendMessage(H.LAUNCH_ACTIVITY, r);
}
在这里创建了ActivityClientRecord,因此ActivityClientRecord和AMS中的ActivityRecord就对应起来了。向主线程发送H.LAUNCH_ACTIVITY消息,消息回调后执行handleLaunchActivity:
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
...
Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
....
handleResumeActivity(r.token, false, r.isForward,
!r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
...
}
....
}
这里调用performLaunchActivity
:
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
// 创建Context
ContextImpl appContext = createBaseContextForActivity(r);
Activity activity = null;
try {
// 通过ClassLoader创建Activity实例
java.lang.ClassLoader cl = appContext.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
r.intent.prepareToEnterProcess();
if (r.state != null) {
r.state.setClassLoader(cl);
}
} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to instantiate activity " + component
+ ": " + e.toString(), e);
}
}
try {
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
if (activity != null) {
//读取Activity信息
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
Configuration config = new Configuration(mCompatConfiguration);
if (r.overrideConfig != null) {
config.updateFrom(r.overrideConfig);
}
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
+ r.activityInfo.name + " with config " + config);
Window window = null;
if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
window = r.mPendingRemoveWindow;
r.mPendingRemoveWindow = null;
r.mPendingRemoveWindowManager = null;
}
appContext.setOuterContext(activity);
// 执行Actiivity attach方法
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, r.configCallback);
if (customIntent != null) {
activity.mIntent = customIntent;
}
r.lastNonConfigurationInstances = null;
checkAndBlockForNetworkAccess();
activity.mStartedActivity = false;
int theme = r.activityInfo.getThemeResource();
if (theme != 0) {
activity.setTheme(theme);
}
activity.mCalled = false;
// Activity onCreate执行
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
if (!activity.mCalled) {
throw new SuperNotCalledException(
"Activity " + r.intent.getComponent().toShortString() +
" did not call through to super.onCreate()");
}
r.activity = activity;
r.stopped = true;
if (!r.activity.mFinished) {
// Activity onStart执行
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);
}
}
}
r.paused = true;
mActivities.put(r.token, r);
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {
}
return activity;
}
这个方法是Activity真正创建实例且onCreate执行的地方,通过调用Activity#attach方法,ActivityClientRecord的token就和Activity联系起来了
3.5.3. BActivity#onStart
onCreate执行完成后,直接调用了activity.performStart();
去执行onStart,因此我们可以得出结论:在Activity的onCreate
和onStart
方法中去处理逻辑,实际没有特别大的区别
3.5.4. BActivity#onResume
performLaunchActivity
调用有返回值,即创建的Activity,如果返回值不为空,则说明创建Activity成功,继续执行handleResumeActivity
final void handleResumeActivity(IBinder token,
boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
ActivityClientRecord r = mActivities.get(token);
if (!checkAndUpdateLifecycleSeq(seq, r, "resumeActivity")) {
return;
}
...
// 执行onResume
r = performResumeActivity(token, clearHide, reason);
...
if (r != null) {
final Activity a = r.activity;
// 向messageQueue发送一个Idle消息
if (!r.onlyLocalRequest) {
r.nextIdle = mNewActivities;
mNewActivities = r;
if (localLOGV) Slog.v(
TAG, "Scheduling idle handler for " + r);
Looper.myQueue().addIdleHandler(new Idler());
}
r.onlyLocalRequest = false;
// 通知AMS完成了Resume操作
if (reallyResume) {
try {
ActivityManager.getService().activityResumed(token);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
}
...
}
performResumeActivity
是Activity的onResume
执行的地方
3.5.5. AActivity#onStop
在执行完成后向住现成的MessageQueue发送了一个idle消息,这个很重要,具体是做什么的呢,我们进去看一下Idler的实现:
private class Idler implements MessageQueue.IdleHandler {
@Override
public final boolean queueIdle() {
ActivityClientRecord a = mNewActivities;
boolean stopProfiling = false;
if (mBoundApplication != null && mProfiler.profileFd != null
&& mProfiler.autoStopProfiler) {
stopProfiling = true;
}
if (a != null) {
mNewActivities = null;
IActivityManager am = ActivityManager.getService();
ActivityClientRecord prev;
do {
if (localLOGV) Slog.v(
TAG, "Reporting idle of " + a +
" finished=" +
(a.activity != null && a.activity.mFinished));
if (a.activity != null && !a.activity.mFinished) {
try {
// 调用ActivityManagerService#activityIdle
am.activityIdle(a.token, a.createdConfig, stopProfiling);
a.createdConfig = null;
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
prev = a;
a = a.nextIdle;
prev.nextIdle = null;
} while (a != null);
}
if (stopProfiling) {
mProfiler.stopProfiling();
}
ensureJitEnabled();
return false;
}
}
看am.activityIdle(a.token, a.createdConfig, stopProfiling)
这里,这种调用在本文中出现过很多次了,我们很容易得出结论:这是一次IPC调用,对应的方法在ActivityManagerService#activityIdle:
@Override
public final void activityIdle(IBinder token, Configuration config, boolean stopProfiling) {
final long origId = Binder.clearCallingIdentity();
synchronized (this) {
ActivityStack stack = ActivityRecord.getStackLocked(token);
if (stack != null) {
ActivityRecord r =
mStackSupervisor.activityIdleInternalLocked(token, false /* fromTimeout */,
false /* processPausingActivities */, config);
if (stopProfiling) {
if ((mProfileProc == r.app) && mProfilerInfo != null) {
clearProfilerLocked();
}
}
}
}
Binder.restoreCallingIdentity(origId);
}
做的工作不多,调用了mStackSupervisor.activityIdleInternalLocked
:
final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout,
boolean processPausingActivities, Configuration config) {
if (DEBUG_ALL) Slog.v(TAG, "Activity idle: " + token);
....
// Atomically retrieve all of the other things to do.
final ArrayList<ActivityRecord> stops = processStoppingActivitiesLocked(r,
true /* remove */, processPausingActivities);
NS = stops != null ? stops.size() : 0;
if ((NF = mFinishingActivities.size()) > 0) {
finishes = new ArrayList<>(mFinishingActivities);
mFinishingActivities.clear();
}
if (mStartingUsers.size() > 0) {
startingUsers = new ArrayList<>(mStartingUsers);
mStartingUsers.clear();
}
...
// Stop any activities that are scheduled to do so but have been
// waiting for the next one to start.
for (int i = 0; i < NS; i++) {
r = stops.get(i);
final ActivityStack stack = r.getStack();
if (stack != null) {
if (r.finishing) {
stack.finishCurrentActivityLocked(r, ActivityStack.FINISH_IMMEDIATELY, false);
} else {
stack.stopActivityLocked(r);
}
}
}
...
return r;
}
processStoppingActivitiesLocked
做的操作就是寻找需要被Stop的Activity,进去看一下:
final ArrayList<ActivityRecord> processStoppingActivitiesLocked(ActivityRecord idleActivity,
boolean remove, boolean processPausingActivities) {
ArrayList<ActivityRecord> stops = null;
final boolean nowVisible = allResumedActivitiesVisible();
// 遍历mStoppingActivities列表,选择其中符合Stop条件的Activity
for (int activityNdx = mStoppingActivities.size() - 1; activityNdx >= 0; --activityNdx) {
ActivityRecord s = mStoppingActivities.get(activityNdx);
boolean waitingVisible = mActivitiesWaitingForVisibleActivity.contains(s);
if (DEBUG_STATES) Slog.v(TAG, "Stopping " + s + ": nowVisible=" + nowVisible
+ " waitingVisible=" + waitingVisible + " finishing=" + s.finishing);
if (waitingVisible && nowVisible) {
mActivitiesWaitingForVisibleActivity.remove(s);
waitingVisible = false;
if (s.finishing) {
s.setVisibility(false);
}
}
if (remove) {
final ActivityStack stack = s.getStack();
final boolean shouldSleepOrShutDown = stack != null
? stack.shouldSleepOrShutDownActivities()
: mService.isSleepingOrShuttingDownLocked();
if (!waitingVisible || shouldSleepOrShutDown) {
if (!processPausingActivities && s.state == PAUSING) {
// Defer processing pausing activities in this iteration and reschedule
// a delayed idle to reprocess it again
removeTimeoutsForActivityLocked(idleActivity);
scheduleIdleTimeoutLocked(idleActivity);
continue;
}
if (DEBUG_STATES) Slog.v(TAG, "Ready to stop: " + s);
if (stops == null) {
stops = new ArrayList<>();
}
stops.add(s);
mStoppingActivities.remove(activityNdx);
}
}
}
return stops;
}
之前在执行AActivity的Pause操作后,我们将AActivity加入到了ActivityStackSupervisor类中一个叫mStoppingActivities的列表中,在这里这个列表就派上用场了,我们会遍历这个列表,从中获取符合条件的Activity并组装到一个新的列表中返回。
完成这个操作后,activityIdleInternalLocked
开始遍历这个返回的列表进Stop操作。
看stack.stopActivityLocked(r)
,凭我20年Android开发经验练就的火眼金睛,感觉这里就是AActivity#onStop触发的地方:
// ActivityStack
final void stopActivityLocked(ActivityRecord r) {
if (r.app != null && r.app.thread != null) {
adjustFocusedActivityStackLocked(r, "stopActivity");
r.resumeKeyDispatchingLocked();
try {
r.app.thread.scheduleStopActivity(r.appToken, r.visible, r.configChangeFlags);
if (shouldSleepOrShutDownActivities()) {
r.setSleeping(true);
}
Message msg = mHandler.obtainMessage(STOP_TIMEOUT_MSG, r);
mHandler.sendMessageDelayed(msg, STOP_TIMEOUT);
} catch (Exception e) {
}
}
}
果然,在这个方法内部执行了r.app.thread.scheduleStopActivity
,这个方法就不进去看了,我们只需要知道它最终调用了r的onStop就可以了
至此,从AActivity跳转BActivity所经历的生命周期就全部完成了。
为什么要用IdleHandler?
我猜测是因为google的工程师认为既然BActivity已经启动了,那么主线程Handler的首要任务还是处理B进程内部的事情,至于AActivity,反正都已经Pause了,就抽个空闲时间告诉AMS把它Stop就可以了。
3.6. 从BActivity返回到AActivity
先回顾一下从BActivity返回AActivity经历的生命周期
BActivity#onPause -> AActivity#onStart -> AActivity#onResume -> BActivity#onStop -> BActivity#onDestroy
先从BActivity的finish方法说起
BActivity的finish方法最终会调用到AMS的finishActivity方法,
// ActivityManagerService
public final boolean finishActivity(IBinder token, int resultCode, Intent resultData,
int finishTask) {
// Refuse possible leaked file descriptors
if (resultData != null && resultData.hasFileDescriptors() == true) {
throw new IllegalArgumentException("File descriptors passed in Intent");
}
synchronized(this) {
ActivityRecord r = ActivityRecord.isInStackLocked(token);
if (r == null) {
return true;
}
// Keep track of the root activity of the task before we finish it
TaskRecord tr = r.getTask();
// 正在结束的Activity所在的ActivityTask
ActivityRecord rootR = tr.getRootActivity();
if (rootR == null) {
Slog.w(TAG, "Finishing task with all activities already finished");
}
final long origId = Binder.clearCallingIdentity();
try {
boolean res;
final boolean finishWithRootActivity =
finishTask == Activity.FINISH_TASK_WITH_ROOT_ACTIVITY;
if (finishTask == Activity.FINISH_TASK_WITH_ACTIVITY
|| (finishWithRootActivity && r == rootR)) {
...
} else {
res = tr.getStack().requestFinishActivityLocked(token, resultCode,
resultData, "app-request", true);
}
return res;
} finally {
Binder.restoreCallingIdentity(origId);
}
}
}
入参的含义:
- token : 准备finish的Activity的Binder token引用
- resultCode: resultCode 字面意思,在onActivityResult接收到的
- resultData: ResultData 字面意思,在onActivityResult接收得到的
- finishTask: 是否将ActivityStack一起finish
在这里我们又和token见面了,在前面从AActivity启动BActivity的流程里我们分析过,这个token是BActivity在AMS中的标识。
ActivityManagerService#finishActivity经过层层调用,会调用到ActivityStack#finishActivityLocked:
final boolean finishActivityLocked(ActivityRecord r, int resultCode, Intent resultData,
String reason, boolean oomAdj, boolean pauseImmediately) {
if (r.finishing) {
Slog.w(TAG, "Duplicate finish request for " + r);
return false;
}
mWindowManager.deferSurfaceLayout();
try {
// 将r标记为finishing
r.makeFinishingLocked();
...
// 将resultCode和resultData设置给resultTo
finishActivityResultsLocked(r, resultCode, resultData);
final boolean endTask = index <= 0 && !task.isClearingToReuseTask();
final int transit = endTask ? TRANSIT_TASK_CLOSE : TRANSIT_ACTIVITY_CLOSE;
if (mResumedActivity == r) {
if (DEBUG_VISIBILITY || DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
"Prepare close transition: finishing " + r);
if (endTask) {
mService.mTaskChangeNotificationController.notifyTaskRemovalStarted(
task.taskId);
}
mWindowManager.prepareAppTransition(transit, false);
// Tell window manager to prepare for this one to be removed.
r.setVisibility(false);
if (mPausingActivity == null) {
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish needs to pause: " + r);
if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
"finish() => pause with userLeaving=false");
// 将当前处于活跃状态的Activity进行Pause
startPausingLocked(false, false, null, pauseImmediately);
}
if (endTask) {
mStackSupervisor.removeLockedTaskLocked(task);
}
} else if (r.state != ActivityState.PAUSING) {
...
} else {
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish waiting for pause of: " + r);
}
return false;
} finally {
mWindowManager.continueSurfaceLayout();
}
}
本方法重点事项
- 将r(即将要finish的Activity)的finishing标记位置为true
- 将resultCode和resultData设置给resultTo,这个resultTo是我们在创建r的时候传入的,在AActivity跳BActivity的流程中我们介绍过,本场景中resultTo指AActivity的token
- 将当前处于活跃状态的Activity进行pause,本场景中活跃状态的Activity就是AActivity
3.6.1. BActivity#onPause
其中startPausingLocked
方法我们在前面已经分析过了,这里就不再赘述了,详细的分析可以看3.5.1章节。通过之前的分析我们知道,startPausingLocked会执行BActvity的onPause回调并最终调用到ActivityManagerService#activityPaused方法,这个放我我们之前也做过分析,最终会调用到ActivityStack#resumeTopActivityInnerLocked,这个方法的调用和BActivity的启动流程略有不同
3.6.2 AActivity#onStart、AActivity#onResume
在调用ActivityStack#resumeTopActivityInnerLocked时,因为我们已经完成对BActivity的Pause,因此,获取栈顶Activity 即next时,拿到的会是AActivity,而AActivity的app和thread均不为空,因此,
判断语句if (next.app != null && next.app.thread != null)
成立,它会走入ActivityStack#resumeTopActivityInnerLocked如下分支:
if (next.app != null && next.app.thread != null) {
if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resume running: " + next
+ " stopped=" + next.stopped + " visible=" + next.visible);
try {
// Deliver all pending results.
ArrayList<ResultInfo> a = next.results;
if (a != null) {
final int N = a.size();
if (!next.finishing && N > 0) {
if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
"Delivering results to " + next + ": " + a);
next.app.thread.scheduleSendResult(next.appToken, a);
}
}
if (next.newIntents != null) {
next.app.thread.scheduleNewIntent(
next.newIntents, next.appToken, false /* andPause */);
}
// Well the app will no longer be stopped.
// Clear app token stopped state in window manager if needed.
next.notifyAppResumed(next.stopped);
EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY, next.userId,
System.identityHashCode(next), next.getTask().taskId,
next.shortComponentName);
next.sleeping = false;
mService.showUnsupportedZoomDialogIfNeededLocked(next);
mService.showAskCompatModeDialogLocked(next);
next.app.pendingUiClean = true;
next.app.forceProcessStateUpTo(mService.mTopProcessState);
next.clearOptionsLocked();
// zhangyulong ResumeNextActivity
next.app.thread.scheduleResumeActivity(next.appToken, next.app.repProcState,
mService.isNextTransitionForward(), resumeAnimOptions);
if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Resumed "
+ next);
} catch (Exception e) {
...
return true;
}
}
}
注意看next.app.thread.scheduleResumeActivity
这里,这个方法最终会调用AActivity的onRestart
、onStart
和onResume
,这个部分的调用大家肯定都轻车熟路了,就不跟进去看了
3.6.3. BActivity#onStop、BActivity#onDestroy
在BActivity启动流程分析中,我们知道在onResume时,会向主线程MessageQueue发送一个IdleHandler,这个IdleHandler最终会调用ActivityStackSupervisor#activityIdleInternalLocked,但这次的调用又跟之前有所不同,因为我们在之前的操作时已经将BActivity置为finishing,因此if (r.finishing)
判断为true,方法调用会执行
final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout,
boolean processPausingActivities, Configuration config) {
if (DEBUG_ALL) Slog.v(TAG, "Activity idle: " + token);
// Atomically retrieve all of the other things to do.
final ArrayList<ActivityRecord> stops = processStoppingActivitiesLocked(r,
true /* remove */, processPausingActivities);
NS = stops != null ? stops.size() : 0;
if ((NF = mFinishingActivities.size()) > 0) {
finishes = new ArrayList<>(mFinishingActivities);
mFinishingActivities.clear();
}
if (mStartingUsers.size() > 0) {
startingUsers = new ArrayList<>(mStartingUsers);
mStartingUsers.clear();
}
// Stop any activities that are scheduled to do so but have been
// waiting for the next one to start.
for (int i = 0; i < NS; i++) {
r = stops.get(i);
final ActivityStack stack = r.getStack();
if (stack != null) {
if (r.finishing) {
// stop 且 pause
stack.finishCurrentActivityLocked(r, ActivityStack.FINISH_IMMEDIATELY, false);
} else {
// 仅stop
stack.stopActivityLocked(r);
}
}
}
return r;
}
方法执行stack.finishCurrentActivityLocked
后,在APP进程对应执行BActivity的onStop
和onDestroy
至此,BActivity返回AActivity的生命周期也执行完毕
4. 后记
很多博客说Activity启动过程会经历两次跨进程,从App进程到AMS,从AMS再到APP进程,实际情况要远比这复杂的多,具体多少次感兴趣的朋友可以数一下。后面的文章会分析onActiivtyResult的执行,敬请期待
(二)onActivityResult执行过程
onActivityResult
onActivityResult机制的使用,属于Android基础知识,我想每一个Android程序员都用过,这里就不多做解释了,看一下使用方式
AActivity跳转BAcitivty并从BActivity返回数据
// AActivity
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
activityName = "AActivity";
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_stack_test);
jumpBtn = findViewById(R.id.jumpBtn);
jumpBtn.setOnClickListener(v -> {
BActivity.start(this, 1);
});
setActivityName();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.d("zyl", activityName + " requestCode = " + requestCode + " resultCode = " + resultCode);
super.onActivityResult(requestCode, resultCode, data);
}
// BActivity
public static void start(Activity activity, int requestCode) {
activity.startActivityForResult(new Intent(activity, BActivity.class), requestCode);
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
activityName = "BActivity";
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_stack_test);
}
@Override
public void finish() {
setResult(102);
super.finish();
}
当BActivity finish时,会将resultCode和requestCode通过AActivity的onActivityResult回传回来
Intent.FLAG_ACTIVITY_FORWARD_RESULT
这是onActivityResult的另一种表现形式,在日常开发中我们经常会遇到如下场景
- 我要从Activity A 跳到B再跳到C
- 我要从Activity C 返回数据给Activity A
- 这种跳转层级有可能有很多层,比如 A ->B -> C -> D -> E等等
有同学看完肯定会说,这个简单啊,每个Activity都实现onActivityResult,每次跳转都使用startActivityForResult不就行了,这样当然可以,但是代码会稍显冗余。实际上,Android系统已经帮我们想好了这种场景的处理方式了
Intent.FLAG_ACTIVITY_FORWARD_RESULT的作用就是最后一个Activity直接调用第一个Activity的onActivityResult
示例:
以AActivity跳转BActivity跳转CActivity为例:
AActivity以startActivityForResult
方式打开BActivity
public static void start(Activity activity, int requestCode) {
Intent intent = new Intent(activity, BActivity.class);
activity.startActivityForResult(intent, requestCode);
}
BActivity以普通方式打开CActivity,设置Intent 的Flag Intent.FLAG_ACTIVITY_FORWARD_RESULT
public static void start(Context context) {
Intent intent = new Intent(context, CActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
context.startActivity(intent);
}
CActivity和BActivity返回后,AActivity会接收到从CActivity传递过来的消息
源码解析
ActivityResult数据的写入
上篇文章我们在解析Activity的finish过程时其实稍微接触了一些onActivity的执行流程,在Activity的finish过程中,会调用到ActivityStack#finishActivityResultsLocked方法
private void finishActivityResultsLocked(ActivityRecord r, int resultCode, Intent resultData) {
// zhangyulong 将结果传递给谁
ActivityRecord resultTo = r.resultTo;
if (resultTo != null) {
if (DEBUG_RESULTS) Slog.v(TAG_RESULTS, "Adding result to " + resultTo
+ " who=" + r.resultWho + " req=" + r.requestCode
+ " res=" + resultCode + " data=" + resultData);
if (resultTo.userId != r.userId) {
if (resultData != null) {
resultData.prepareToLeaveUser(r.userId);
}
}
if (r.info.applicationInfo.uid > 0) {
mService.grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid,
resultTo.packageName, resultData,
resultTo.getUriPermissionsLocked(), resultTo.userId);
}
// zhangyulong 将ActivityResult结果放在resultTo中保存
resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode,
resultData);
r.resultTo = null;
}
else if (DEBUG_RESULTS) Slog.v(TAG_RESULTS, "No result destination from " + r);
r.results = null;
r.pendingResults = null;
r.newIntents = null;
r.icicle = null;
}
入参含义:
- r:即将finish的Activity
- resultCode: 要传递的resultCode
- resultData:要传递的Intent
这个方法将result信息封装成一个ResultIfo对象,并保存在列表中
ActivityResult数据的传递
在上篇文章中,我们在分析Activity的finish流程时提到过ActivityStack#resumeTopActivityInnerLocked方法,这个方法还有一个作用就是向上一个Activity,即resultTo传递ActivityResult
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
...
if (next.app != null && next.app.thread != null) {
...
synchronized(mWindowManager.getWindowManagerLock()) {
...
try {
// Deliver all pending results.
ArrayList<ResultInfo> a = next.results;
if (a != null) {
final int N = a.size();
if (!next.finishing && N > 0) {
if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
"Delivering results to " + next + ": " + a);
next.app.thread.scheduleSendResult(next.appToken, a);
}
}
...
}
}
...
} else {
....
}
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return true;
}
通过调用next.app.thread.scheduleSendResult(next.appToken, a)
将ResultInfo发送到App进程中对应的Activity中,并回调onActivityResult
方法
Intent.FLAG_ACTIVITY_FORWARD_RESULT的实现
上篇文章我们分析过,Activity的启动流程会调用ActivityStarter#startActivity,这个方法有对Intent.FLAG_ACTIVITY_FORWARD_RESULT的处理,废话不多说,直接看源码:
private int startActivity(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, TaskRecord inTask) {
...
ActivityRecord sourceRecord = null;
ActivityRecord resultRecord = null;
if (resultTo != null) {
// zhangyulong 获取启动的源activity
sourceRecord = mSupervisor.isInAnyStackLocked(resultTo);
if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
"Will send result to " + resultTo + " " + sourceRecord);
if (sourceRecord != null) {
if (requestCode >= 0 && !sourceRecord.finishing) {
resultRecord = sourceRecord;
}
}
}
if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
// 添加Intent.FLAG_ACTIVITY_FORWARD_RESULT启动的Activity不能使用startActivityForResult启动
if (requestCode >= 0) {
ActivityOptions.abort(options);
return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
}
// 将源Activity的resultTo赋值给目标Activity
resultRecord = sourceRecord.resultTo;
if (resultRecord != null && !resultRecord.isInStackLocked()) {
resultRecord = null;
}
resultWho = sourceRecord.resultWho;
requestCode = sourceRecord.requestCode;
sourceRecord.resultTo = null;
if (resultRecord != null) {
resultRecord.removeResultsLocked(sourceRecord, resultWho, requestCode);
}
if (sourceRecord.launchedFromUid == callingUid) {
callingPackage = sourceRecord.launchedFromPackage;
}
}
...
return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true,
options, inTask, outActivity);
}
代码比较简单,主要就是判断Intent中是否带有Intent.FLAG_ACTIVITY_FORWARD_RESULT标签,如果有,则将源Activity的resultTo赋值给目标Activity
如果有多个中间Activity,比如使用这种方式启动ABCDE五个Activity,其中,BCD都是中间Activity,
那么resultTo的传递过程如下:
- A启动B,A作为resultTo传递给B
- B启动C,添加Intent.FLAG_ACTIVITY_FORWARD_RESULT,C获取B的ResultTo即A
- C启动D,添加Intent.FLAG_ACTIVITY_FORWARD_RESULT,D获取C的ResultTo即A
- D启动E,添加Intent.FLAG_ACTIVITY_FORWARD_RESULT,E获取D的ResultTo即A
- 从E逐级返回,当E返回时,将ResultInfo赋值给A,当返回到A时,触发next.app.thread.scheduleSendResult(next.appToken, a)
(三)AMS中Activity栈管理详解
1.前言
Activity栈管理是AMS的另一个重要功能,栈管理又和Activity的启动模式和startActivity时所设置的Flag息息相关,Activity栈管理的主要处理逻辑是在ActivityStarter#startActivityUnchecked方法中,本文也会围绕着这个方法进进出出,反复摩擦,直到脑海中都是它的形状。goolge的工程师起名还是很讲究的,为什么要带Unchecked呢? Unchecked-不确定,是因为在执行这个方法时,我要启动哪个Activity还没决定呢,具体为什么,我想看过这篇文章你就明白了。
2.Activity栈管理相关类
2.1ActivityStackSupervisor
顾名思义,Activity栈的功能提供者和管理者
2.2.ActivityDisplay
表示一个屏幕,Android支持三种屏幕:主屏幕,外接屏幕(HDMI等),虚拟屏幕(投屏)。一般情况下,即只有主屏幕时,ActivityStackSupervisor与ActivityDisplay都是系统唯一
2.3.TaskRecord
ActivityTask记录, Task是我们管理Activity栈的重要单元,它的表现形式与逻辑和Activity启动模式息息相关,也是本文重点要分析的
2.4.ActivityStack
针对ActivityRecord 和 TaskRecord进行管理,记录ActivityRecord的状态和TaskRecord的状态。在Android N之前只有两种ActivityStack:homeStack(launcher和recents Activity)和其他。Android N开始有5种,增加了DockedStack(分屏Activity)、PinnedStack(画中画Activity)、freeformstack(自由模式Activity),虽然它名字叫ActivityStack,但是跟我们熟知的数据结构中的栈基本上没啥关系,这也是有可能会增加一点理解难度的地方
2.5.关系图:
先说一下关系:
- 一个ActivityDisplay包含多个ActivityStack
- 一个ActivityStack包含多个TaskRecord
- 一个TaskRecord包含多个ActivityRecord
3.启动模式
3.1.standard
标准启动模式,启动Activity时依次向栈顶添加ActivityRecord,返回时依次推出,示例:AActivity打开BActivity打开CActivity
]
这是基本的Activity启动模式,需要注意的点不太多
3.1.1.Intent.FLAG_ACTIVITY_CLEAR_TOP
还是刚才的案例,如果依次打开AActivity->BActivity->CActivity->DActivity,此时在DActivity打开AActivity时Intent添加Flag Intent.FLAG_ACTIVITY_CLEAR_TOP,系统会从BActivity开始依次将Task中的Activity依次销毁,直到DActivity,因为DActivity处于活跃状态,因此会先执行onPause,在onPause后,会销毁原来的AActivity,然后打开新的AActivity,最后执行DActivity的onStop和onDestory
流程图如下:
log:
3.1.2.源码分析
3.1.2.1.加入TaskRecord
摘抄ActivityStarter#startActivityUnchecked部分代码如下:
if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
&& (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
newTask = true;
// zhangyulong 使用一个旧的Task 或者新建一个
result = setTaskFromReuseOrCreateNewTask(
taskToAffiliate, preferredLaunchStackId, topStack);
} else if (mSourceRecord != null) {
// zhangyulong 使用源Activity的task
result = setTaskFromSourceRecord();
} else if (mInTask != null) {
// zhangyulong 使用启动时传递的task
result = setTaskFromInTask();
} else {
// zhangyulong 理论上的可能,不可能走到这里
setTaskToCurrentTopOrCreateNewTask();
}
if (result != START_SUCCESS) {
return result;
}
因为我们使用标准模式启动,因此,resultTo和mSourceRecord均不为空,这段逻辑会执行setTaskFromSourceRecord:
private int setTaskFromSourceRecord() {
...
addOrReparentStartingActivity(sourceTask, "setTaskFromSourceRecord");
return START_SUCCESS;
}
addOrReparentStartingActivity最终会执行TaskRecord#addActivityAtIndex:
void addActivityAtIndex(int index, ActivityRecord r) {
...
mActivities.add(index, r);
...
}
向对应的ActivityRecord中的mActivities添加本条记录,完成加入TaskRecord的操作
3.1.2.2.standard + Intent.FLAG_ACTIVITY_CLEAR_TOP
回到ActivityStarter#startActivityUnchecked,摘抄部分逻辑如下:
if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0) {
// 将ActivityTask目标Actiivty之上的Activity全部清空,返回值top为可以复用的Activity
ActivityRecord top = sourceTask.performClearTaskLocked(mStartActivity, mLaunchFlags);
mKeepCurTransition = true;
// 如果可复用的Activity不为空,直接调用它的onNewIntent方法并将其resume
if (top != null) {
ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.getTask());
deliverNewIntent(top);
mTargetStack.mLastPausedActivity = null;
if (mDoResume) {
mSupervisor.resumeFocusedStackTopActivityLocked();
}
ActivityOptions.abort(mOptions);
return START_DELIVERED_TO_TOP;
}
}
重点看performClearTaskLocked
,这里是将目标Activity顶部元素清空的逻辑
/***
* newR: 需要启动的新Activity
* launchFlags: 新Activity的启动模式
*/
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) {
continue;
}
// 在目标Task中找到了和新Activity相同的记录
if (r.realActivity.equals(newR.realActivity)) {
final ActivityRecord ret = r;
//将在其之上的Activity全部清除
for (++activityNdx; activityNdx < numActivities; ++activityNdx) {
r = mActivities.get(activityNdx);
if (r.finishing) {
continue;
}
ActivityOptions opts = r.takeOptionsLocked();
if (opts != null) {
ret.updateOptionsLocked(opts);
}
// 执行finishActivityLocked,如果Activity已经stop,会直接执行onDestroy,
// 如果Activity还在活跃,则会先执行onPause
if (mStack != null && mStack.finishActivityLocked(
r, Activity.RESULT_CANCELED, null, "clear-task-stack", false)) {
--activityNdx;
--numActivities;
}
}
// ActivityInfo.LAUNCH_MULTIPLE == standrad
// 如果新Activity的launchMode是standard,且launchFlag没有FLAG_ACTIVITY_SINGLE_TOP,则将之前task
// 内的activity也结束,以便建立新的
if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE
&& (launchFlags & Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0
&& !ActivityStarter.isDocumentLaunchesIntoExisting(launchFlags)) {
if (!ret.finishing) {
if (mStack != null) {
mStack.finishActivityLocked(
ret, Activity.RESULT_CANCELED, null, "clear-task-top", false);
}
// 返回空,说明不执行onNewIntent
return null;
}
}
return ret;
}
}
return null;
}
看完这部分代码,我想FLAG_ACTIVITY_CLEAR_TOP是怎么工作的大家也就明白了。
3.2.singleTop
singleTop:栈顶唯一,它和standrad的区别在于,如果是standrad模式,在栈顶启动一个相同的Activity,会创建一个新的Activity实例,如果是singleTop模式,在栈顶启动相同的Activity则只会调用原有Activity的onNewIntent,如果原Activity不在栈顶,那么表现形式就和standrad相同
3.2.1.流程图:
3.2.1.1.原Activity不在栈顶
3.2.1.2.原Activity在栈顶
3.2.2.singleTop + Intent.FLAG_ACTIVITY_CLEAR_TOP
现在设想一种场景,AActivitylanchMode为singleTop,在AActivity的基础上依次打开了BActivity、CActivity, 在CActivity再次打开AActivity,但打开时设置Intent属性Intent.FLAG_ACTIVITY_CLEAR_TOP,此时的启动流程:
3.2.3.log
3.2.3.1.原Activity不在栈顶
3.2.3.2.原Activity在栈顶
3.2.3.3.原Actiivty在栈顶且设置Intent.FLAG_ACTIVITY_CLEAR_TOP
3.2.3.源码分析
我们又要进入ActivityStarter#startActivityUnchecked方法了, startActivityUnchecked:你要对我负责555…
摘抄startActivityUnchecked
方法中关于singleTop模式的处理如下:
// 要启动的Activity正好是当前在栈顶的Activity
// 当前聚焦的ActivityStack
final ActivityStack topStack = mSupervisor.mFocusedStack;
// 当前聚焦的ActivityStack中的栈顶Actiivty
final ActivityRecord topFocused = topStack.topActivity();
// 当前栈顶Activity
final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
final boolean dontStart = top != null && mStartActivity.resultTo == null
&& top.realActivity.equals(mStartActivity.realActivity)
&& top.userId == mStartActivity.userId
&& top.app != null && top.app.thread != null
&& ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
|| mLaunchSingleTop || mLaunchSingleTask);
// dontStart为true说明可以直接复用栈顶Activity
if (dontStart) {
// For paranoia, make sure we have correctly resumed the top activity.
topStack.mLastPausedActivity = null;
if (mDoResume) {
mSupervisor.resumeFocusedStackTopActivityLocked();
}
ActivityOptions.abort(mOptions);
if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
// We don't need to start a new activity, and the client said not to do
// anything if that is the case, so this is it!
return START_RETURN_INTENT_TO_CALLER;
}
// zhangyulong singleTop sigleTask onNewIntent 执行
deliverNewIntent(top);
return START_DELIVERED_TO_TOP;
}
需要注意的是,当我们设置目标Activity launchMode是singleTop时,判断条件用的是mLaunchSingleTop,而(mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP是指启动时设置的Intent的Flag属性。这两种方式都能达到singleTop的效果。
3.2.3.1.singleTop + Intent.FLAG_ACTIVITY_CLEAR_TOP
这部分的逻辑处理和standard时差不多,还是performClearTaskLocked方法,这个方法在3.1.2.2章节已经分析过了,这里摘抄部分逻辑如下:
// ActivityInfo.LAUNCH_MULTIPLE == standrad
// 如果新Activity的launchMode是standard,且launchFlag没有FLAG_ACTIVITY_SINGLE_TOP,则将之前task
// 内的activity也结束,以便建立新的
if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE
&& (launchFlags & Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0
&& !ActivityStarter.isDocumentLaunchesIntoExisting(launchFlags)) {
if (!ret.finishing) {
if (mStack != null) {
mStack.finishActivityLocked(
ret, Activity.RESULT_CANCELED, null, "clear-task-top", false);
}
// 返回空,说明不执行onNewIntent
return null;
}
}
因为我们的launchMode是FLAG_ACTIVITY_SINGLE_TOP,条件不成立,不会销毁命中的原Activity,但原Actiivty上面的记录均已销户,此时它已经是栈顶Activity了,继续执行会执行到startActivityUnchecked
方法中3.2.3章节部分,和上面的逻辑就一致了。
3.3 singleTask
singleTask: 栈内唯一,如果Activity设置了launchMode为singleTask,那么在整个ActivityStack中有且仅有一个实例存在。有些朋友看到它名字叫singleTask,就想当然的认为它是Task内唯一的,我们不要被它的名字骗了。需要注意的一点是,singleTask模式启动是默认clearTop的。
3.3.1 启动流程
场景一
假设AActivity的launchMode为singleTask,AActivity后依次启动BActivity和CActivity, CActivity又启动了AActivity,
那么这个过程经历的流程如下:
log:
场景二:
假设AActivity和BActivity都是Standard,CActivity为singleTask,CActiivty再次启动CActivity,这个过程的启动流程:
log:
场景三:
看完前面两种场景,肯定会有同学不服气,你不是说singleTask是栈内唯一么,这两种场景都是task内的处理啊,那不就应该是task内唯一么,你说栈内唯一拿出证据来啊!别着急,证据马上来。
现在假设AActivity是singleTask, BActivity是standard, BActivity打开CActivity时创建新的Task, 然后CActivity再次打开AActivity
流程如下:
- AActivity在其自身所在task启动BActivity
- BActivity在启动CActivity时创建新的Task
- CActivity启动AActivity时将AActivity所在的Task移到顶部
- AActivity将BActivity清除并重新启动
流程图:
看下log是不是这样:
log也验证了这个说法的正确性,从这个案例中我们看出,虽然AB在一个task, C在另一个task,但C启动A的时候,并没有在其自身的task启动,而是操作AB所在的task。因此,singeTask是栈内唯一的。
3.3.2 singeTask源码分析
再进入一次ActivityStarter#startActivityUnchecked一次,此时startActivityUnchecked
内心活动:别进了,再进就怀孕了!!
为什么说singleTask自带clearTop属性呢? 看下startActivityUnchecked
的这段逻辑:
// 如果启动Intent设置了FLAG_ACTIVITY_CLEAR_TOP或者目标Activity启动模式为singleInstance或者singleTask,执行以下逻辑
if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
|| isDocumentLaunchesIntoExisting(mLaunchFlags)
|| mLaunchSingleInstance || mLaunchSingleTask) {
final TaskRecord task = reusedActivity.getTask();
// 将与新Actiivty在Task内相同的Activity的顶部元素清空
final ActivityRecord top = task.performClearTaskForReuseLocked(mStartActivity,
mLaunchFlags);
...
}
那么task切换到栈顶是在哪里呢,这段逻辑执行完成后,就会执行到Task切换的逻辑了,代码:
// 将目标Activity所在Task移动到栈顶
reusedActivity = setTargetStackAndMoveToFrontIfNeeded(reusedActivity);
当前面的逻辑完成后,可复用用的Activity就已经在Task顶部,而Task也已经在Stack顶部,完事俱备,只欠东风,继续执行startActivityUnchecked
会执行到3.2.3的内容,和singleTop的处理是一致的,最终回调了目标Activity的onNewIntent
。
3.4 singleInstance
singleInstance这个启动模式比sigleTask更NB一些,它不光在栈内唯一,而且还独占一个Task,一看就是那种有独立办公室的老板,跟其他打工人完全不是一个等级的。关于singleInstance的栈管理和切换,你可以把它理解成只有一个singleTask的Activity存在的Task就比较好理解了,上面我们也已经分析过了。
4. Intent.FLAG_ACTIVITY_NEW_TASK、taskAffinity、新Task的创建
先看几个有意思的案例:
现在有两个Activity,分别是AActivity和BActivity,我们先设置A和B均为standard,在A启动B时设置Intent.FLAG_ACTIVITY_NEW_TASK,跳转时Task会新建么?
看一下log:
从图上我们看到,A和B的TaskId都是305,也就是没有创建新的Task,怎么回事,Intent.FLAG_ACTIVITY_NEW_TASK怎么失效了?
这个时候把B的launchMode设置为singleTask呢?
看一下log:
依然没有生效!!
这个时候保持B的launchMode为singleTask, 设置B的taskAffinity为".b"试一下:
生效了!!
这个时候把Intent.FLAG_ACTIVITY_NEW_TASK取消,保持B的launchMode为singleTask, 设置B的taskAffinity为".b"试一下:
生效了!
这个时候把Intent.FLAG_ACTIVITY_NEW_TASK取消,修改B的launchMode为standard, 设置B的taskAffinity为".b"试一下:
没生效!
这个时候把B的taskAffinity删掉,设置B为singleInstace试一下:
又生效了!!
看到这里是不是感觉已经晕了,那到底啥时候生效晒时候失效啊!别着急,看完源码我们再做总结
我们又要进入ActivityStarter#startActivityUnchecked方法了, startActivityUnchecked:不挣扎了,已经有你的形状了…
4.1 Intent.FLAG_ACTIVITY_NEW_TASK的自动设置
startActivityUnchecked前面几行代码执行了一个叫做computeLaunchingTaskFlags
的方法,这个方法的作用是根据新Activity的launchMode对launchFlag
做处理:
private void computeLaunchingTaskFlags() {
...
if (mInTask == null) {
if (mSourceRecord == null) {
...
} else if (mSourceRecord.launchMode == LAUNCH_SINGLE_INSTANCE) {
// 如果源Activity是singleInstance,则新启动Activity时自动添加launchFlag FLAG_ACTIVITY_NEW_TASK
mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
} else if (mLaunchSingleInstance || mLaunchSingleTask) {
// 如果新Activity的launchMode是singleInstace或者singleTask,则新启动Activity时自动添加launchFlag FLAG_ACTIVITY_NEW_TASK
mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
}
}
}
也就是说,如果一个Actiivty是singleInstacne的,那么不管是别人启动它还是它启动别人,都会自动添加启动flag FLAG_ACTIVITY_NEW_TASK, 如果是singeTask,则只有别人启动它时才会这样设置
4.2 taskAffinity的识别
4.1部分的逻辑执行后,startActivityUnchecked
会执行getReusableIntentActivity
方法,这个方法主要是寻找ActivityStack中是否有可复用的Task, 返回值会可复用Task的顶部元素:
private ActivityRecord getReusableIntentActivity() {
// 设置了launchFlag为FLAG_ACTIVITY_NEW_TASK或者 launchMode为singleInstance或singleTask
boolean putIntoExistingTask = ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 &&
(mLaunchFlags & FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
|| mLaunchSingleInstance || mLaunchSingleTask;
// inTask为null 且requestCode小于0(即resultTo == null)
putIntoExistingTask &= mInTask == null && mStartActivity.resultTo == null;
ActivityRecord intentActivity = null;
if (mOptions != null && mOptions.getLaunchTaskId() != -1) {
final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
intentActivity = task != null ? task.getTopActivity() : null;
} else if (putIntoExistingTask) {
if (mLaunchSingleInstance) {
// 如果launchMode为singleInstance,只要当前状态下Stack中有和要启动的Activity相同的记录,就说明可以复用
intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
mStartActivity.isHomeActivity());
} else if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
// 没研究
intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
!mLaunchSingleTask);
} else {
// 其他情况查找Stack中是否有适用的Task和可复用的Actiivty
intentActivity = mSupervisor.findTaskLocked(mStartActivity, mSourceDisplayId);
}
}
return intentActivity;
}
findActivityLocked逻辑比较简单,就是在整个Stack中遍历Activity作对比,重点看ActivitySuperVisor#findTaskLocked,ActivitySuperVisor#findTaskLocked中调用了ActivityStack#findTaskLocked,看一下重要逻辑:
void findTaskLocked(ActivityRecord target, FindTaskResult result) {
...
} else if (!isDocument && !taskIsDocument
&& result.r == null && task.rootAffinity != null) {
// 如果Task的rootAffinity和新Activity的taskAffinity匹配,则说明有可复用的栈
// ,task的rootAffinity一般由底部Actiivty决定,不特意设置的话,一般使用包名
if (task.rootAffinity.equals(target.taskAffinity)) {
result.r = r;
result.matchedByRootAffinity = true;
}
} else if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Not a match: " + task);
}
}
这里就是匹配taskAffinity的地方。回到getReusableIntentActivity
方法,说一下它的返回值逻辑:
- 如果launchMode是singleInstance,则判断当前stack中是否有相同Actiivty,如果有则返回对应Actiivty,否则是null
- 如果launchMode是其他,则判断当前stack中是否有可以匹配其affinity的Task,如果有则返回对应Task顶部Activity,否则是null
4.3 是否创建新task的识别
如果getReusableIntentActivity
方法返回值不为null,startActivityUncheck
后面的逻辑会执行setTaskFromReuseOrCreateNewTask
方法:
private void setTaskFromIntentActivity(ActivityRecord intentActivity) {
if ((mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
== (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) {
final TaskRecord task = intentActivity.getTask();
task.performClearTaskLocked();
// 设置启动新Actiivty时所使用的task
mReuseTask = task;
mReuseTask.setIntent(mStartActivity);
}
...
}
注意,这个方法执行的必要条件是getReusableIntentActivity
方法返回值不为null,入参intentActivity即是getReusableIntentActivity
方法的返回值。
因此,假如mReuseTask 为null,则启动Actiivty时会创建新的task,否则向mReuseTask 中添加,逻辑如下:
private int setTaskFromReuseOrCreateNewTask(
TaskRecord taskToAffiliate, int preferredLaunchStackId, ActivityStack topStack) {
mTargetStack = computeStackFocus(
mStartActivity, true, mLaunchBounds, mLaunchFlags, mOptions);
if (mReuseTask == null) {
// 创建新的Task
final TaskRecord task = mTargetStack.createTaskRecord(
mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
mNewTaskIntent != null ? mNewTaskIntent : mIntent, mVoiceSession,
mVoiceInteractor, !mLaunchTaskBehind /* toTop */, mStartActivity.mActivityType);
// 向新Task中添加
addOrReparentStartingActivity(task, "setTaskFromReuseOrCreateNewTask - mReuseTask");
...
} else {
// 向旧task中添加
addOrReparentStartingActivity(mReuseTask, "setTaskFromReuseOrCreateNewTask");
}
...
return START_SUCCESS;
}
4.4 总结
通过上面的代码分析,我们可以总结出在Activity启动过程中创建新Task的条件:
- standard、singleTop模式 Intent.FLAG_ACTIVITY_NEW_TASK 和taskAffinity必须同时设置
- sinlgeTask模式 只需设置taskAffinity,Intent.FLAG_ACTIVITY_NEW_TASK 可有可无
- singeInstance Intent.FLAG_ACTIVITY_NEW_TASK 和taskAffinity均可有可无