本文主要分析
从当前activity打开另一个acivity(这里也包括了一个app打开另一个app的activity的情况)
通过第一篇文章我们知道了,当activity onResume后,原来新添加的activityRecord被最终废弃掉了,用了原来activityStack里的activityRecord
现在由于是打开了新的activity,所以新建的activityRecord必然要添加taskRecord中,有可能还要新建activityStack,来看看ams里具体的操作吧
下文MainActivity简单来说就是sourceActivity
TestActiivty就是要打开的activity
这里前期的流程和上文一模一样,这里就不多说了
一直到ActivityStater中找到可复用的activity这里,由于是标准模式的
private ActivityRecord getReusableIntentActivity() {
// We may want to try to place the new activity in to an existing task. We always
// do this if the target activity is singleTask or singleInstance; we will also do
// this if NEW_TASK has been requested, and there is not an additional qualifier telling
// us to still place it in a new task: multi task, always doc mode, or being asked to
// launch this as a new task behind the current one.
boolean putIntoExistingTask = ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 &&
(mLaunchFlags & FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
|| isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK);
// If bring to front is requested, and no result is requested and we have not been given
// an explicit task to launch in to, and we can find a task that was started with this
// same component, then instead of launching bring that one to the front.
putIntoExistingTask &= mInTask == null && mStartActivity.resultTo == null;
ActivityRecord intentActivity = null;
if (mOptions != null && mOptions.getLaunchTaskId() != -1) {
final TaskRecord task = mRootActivityContainer.anyTaskForId(mOptions.getLaunchTaskId());
intentActivity = task != null ? task.getTopActivity() : null;
} else if (putIntoExistingTask) {
if (LAUNCH_SINGLE_INSTANCE == mLaunchMode) {
// There can be one and only one instance of single instance activity in the
// history, and it is always in its own unique task, so we do a special search.
intentActivity = mRootActivityContainer.findActivity(mIntent, mStartActivity.info,
mStartActivity.isActivityTypeHome());
} else if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
// For the launch adjacent case we only want to put the activity in an existing
// task if the activity already exists in the history.
intentActivity = mRootActivityContainer.findActivity(mIntent, mStartActivity.info,
!(LAUNCH_SINGLE_TASK == mLaunchMode));
} else {
// Otherwise find the best task to put the activity in.
intentActivity =
mRootActivityContainer.findTask(mStartActivity, mPreferredDisplayId);
}
}
if (intentActivity != null
&& (mStartActivity.isActivityTypeHome() || intentActivity.isActivityTypeHome())
&& intentActivity.getDisplayId() != mPreferredDisplayId) {
// Do not reuse home activity on other displays.
intentActivity = null;
}
return intentActivity;
}
所以putIntoExistingTask为false,上一篇是走到了mRootActivityContainer.findTask中
所以返回复用的activityRecord是null,这里也就走了上一篇没走的地方
final ActivityStack topStack = mRootActivityContainer.getTopDisplayFocusedStack();
final ActivityRecord topFocused = topStack.getTopActivity();
final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
final boolean dontStart = top != null && mStartActivity.resultTo == null
&& top.mActivityComponent.equals(mStartActivity.mActivityComponent)
&& top.mUserId == mStartActivity.mUserId
&& top.attachedToProcess()
&& ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
|| isLaunchModeOneOf(LAUNCH_SINGLE_TOP, LAUNCH_SINGLE_TASK))
// This allows home activity to automatically launch on secondary display when
// display added, if home was the top activity on default display, instead of
// sending new intent to the home activity on default display.
&& (!top.isActivityTypeHome() || top.getDisplayId() == mPreferredDisplayId);
if (dontStart) {
这里判断了component.很明显,这里是不相等的,一个是MainActivity一个是TestActivity,如果是doStart应该是singleTop或者是singleTask模式的
接下来走这个代码段
if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
&& (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
newTask = true;
result = setTaskFromReuseOrCreateNewTask(taskToAffiliate);
} else if (mSourceRecord != null) {
result = setTaskFromSourceRecord();
} else if (mInTask != null) {
result = setTaskFromInTask();
} else {
// This not being started from an existing activity, and not part of a new task...
// just put it in the top task, though these days this case should never happen.
result = setTaskToCurrentTopOrCreateNewTask();
}
if (result != START_SUCCESS) {
return result;
}
第一个是newTask的情况分析,这里下篇再说
重点分析下setTaskFromSourceRecord方法
private int setTaskFromSourceRecord() {
if (mService.getLockTaskController().isLockTaskModeViolation(
mSourceRecord.getTaskRecord())) {
Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
return START_RETURN_LOCK_TASK_MODE_VIOLATION;
}
final TaskRecord sourceTask = mSourceRecord.getTaskRecord();
final ActivityStack sourceStack = mSourceRecord.getActivityStack();
if (mRestrictedBgActivity && !sourceTask.containsAppUid(mCallingUid)) {
if (handleBackgroundActivityAbort(mStartActivity)) {
return START_ABORTED;
}
}
// We only want to allow changing stack in two cases:
// 1. If the target task is not the top one. Otherwise we would move the launching task to
// the other side, rather than show two side by side.
// 2. If activity is not allowed on target display.
final int targetDisplayId = mTargetStack != null ? mTargetStack.mDisplayId
: sourceStack.mDisplayId;
final boolean moveStackAllowed = sourceStack.topTask() != sourceTask
|| !mStartActivity.canBeLaunchedOnDisplay(targetDisplayId);
if (moveStackAllowed) {
mTargetStack = getLaunchStack(mStartActivity, mLaunchFlags,
mStartActivity.getTaskRecord(), mOptions);
// If target stack is not found now - we can't just rely on the source stack, as it may
// be not suitable. Let's check other displays.
if (mTargetStack == null && targetDisplayId != sourceStack.mDisplayId) {
// Can't use target display, lets find a stack on the source display.
mTargetStack = mRootActivityContainer.getValidLaunchStackOnDisplay(
sourceStack.mDisplayId, mStartActivity, mOptions, mLaunchParams);
}
if (mTargetStack == null) {
// There are no suitable stacks on the target and source display(s). Look on all
// displays.
mTargetStack = mRootActivityContainer.getNextValidLaunchStack(
mStartActivity, -1 /* currentFocus */);
}
}
if (mTargetStack == null) {
mTargetStack = sourceStack;
} else if (mTargetStack != sourceStack) {
sourceTask.reparent(mTargetStack, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT, !ANIMATE,
DEFER_RESUME, "launchToSide");
}
final TaskRecord topTask = mTargetStack.topTask();
if (topTask != sourceTask && !mAvoidMoveToFront) {
mTargetStack.moveTaskToFrontLocked(sourceTask, mNoAnimation, mOptions,
mStartActivity.appTimeTracker, "sourceTaskToFront");
} else if (mDoResume) {
mTargetStack.moveToFront("sourceStackToFront");
}
if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0) {
// In this case, we are adding the activity to an existing task, but the caller has
// asked to clear that task if the activity is already running.
ActivityRecord top = sourceTask.performClearTaskLocked(mStartActivity, mLaunchFlags);
mKeepCurTransition = true;
if (top != null) {
ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.getTaskRecord());
deliverNewIntent(top);
// For paranoia, make sure we have correctly resumed the top activity.
mTargetStack.mLastPausedActivity = null;
if (mDoResume) {
mRootActivityContainer.resumeFocusedStacksTopActivities();
}
ActivityOptions.abort(mOptions);
return START_DELIVERED_TO_TOP;
}
} else if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
// In this case, we are launching an activity in our own task that may already be
// running somewhere in the history, and we want to shuffle it to the front of the
// stack if so.
final ActivityRecord top = sourceTask.findActivityInHistoryLocked(mStartActivity);
if (top != null) {
final TaskRecord task = top.getTaskRecord();
task.moveActivityToFrontLocked(top);
top.updateOptionsLocked(mOptions);
ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, task);
deliverNewIntent(top);
mTargetStack.mLastPausedActivity = null;
if (mDoResume) {
mRootActivityContainer.resumeFocusedStacksTopActivities();
}
return START_DELIVERED_TO_TOP;
}
}
// An existing activity is starting this new activity, so we want to keep the new one in
// the same task as the one that is starting it.
addOrReparentStartingActivity(sourceTask, "setTaskFromSourceRecord");
if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
+ " in existing task " + mStartActivity.getTaskRecord()
+ " from source " + mSourceRecord);
return START_SUCCESS;
}
这里分析下
if (mTargetStack == null) {
mTargetStack = sourceStack;
} else if (mTargetStack != sourceStack) {
sourceTask.reparent(mTargetStack, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT, !ANIMATE,
DEFER_RESUME, "launchToSide");
}
final TaskRecord topTask = mTargetStack.topTask();
if (topTask != sourceTask && !mAvoidMoveToFront) {
mTargetStack.moveTaskToFrontLocked(sourceTask, mNoAnimation, mOptions,
mStartActivity.appTimeTracker, "sourceTaskToFront");
} else if (mDoResume) {
mTargetStack.moveToFront("sourceStackToFront");
}
首先会把sorceStack赋值给mTargetStack,并且很明显由于现在一个activityStack就一个taskRecord,所以两个taskRecord是相等的,所以会调用
mTargetStack.moveToFront
把当前的actiivtyStack移到最上面
然后很明显,加到了原来的taskRecord的栈上
private void addOrReparentStartingActivity(TaskRecord parent, String reason) {
if (mStartActivity.getTaskRecord() == null || mStartActivity.getTaskRecord() == parent) {
parent.addActivityToTop(mStartActivity);
} else {
mStartActivity.reparent(parent, parent.mActivities.size() /* top */, reason);
}
}
在addActivityToTop方法里也确实在原有的taskRecord的mActivities列表上添加了activityRecord
final int size = mActivities.size();
if (index == size && size > 0) {
final ActivityRecord top = mActivities.get(size - 1);
if (top.mTaskOverlay) {
// Place below the task overlay activity since the overlay activity should always
// be on top.
index--;
}
}
index = Math.min(size, index);
mActivities.add(index, r);
updateEffectiveIntent();
if (r.isPersistable()) {
mService.notifyTaskPersisterLocked(this, false);
}
if (r.mAppWindowToken != null) {
// Only attempt to move in WM if the child has a controller. It is possible we haven't
// created controller for the activity we are starting yet.
mTask.positionChildAt(r.mAppWindowToken, index);
}
// Make sure the list of display UID whitelists is updated
// now that this record is in a new task.
mService.mRootActivityContainer.updateUIDsPresentOnDisplay();
}
此时仅仅是一个list加了,而activityRecord对应的mAppWindowToken还没有
接下来进行了如下的操作
if (newTask) {
EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, mStartActivity.mUserId,
mStartActivity.getTaskRecord().taskId);
}
ActivityStack.logStartActivity(
EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.getTaskRecord());
mTargetStack.mLastPausedActivity = null;
mRootActivityContainer.sendPowerHintForLaunchStartIfNeeded(
false /* forceSend */, mStartActivity);
mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,
mOptions);
if (mDoResume) {
final ActivityRecord topTaskActivity =
mStartActivity.getTaskRecord().topRunningActivityLocked();
if (!mTargetStack.isFocusable()
|| (topTaskActivity != null && topTaskActivity.mTaskOverlay
&& mStartActivity != topTaskActivity)) {
// If the activity is not focusable, we can't resume it, but still would like to
// make sure it becomes visible as it starts (this will also trigger entry
// animation). An example of this are PIP activities.
// Also, we don't want to resume activities in a task that currently has an overlay
// as the starting activity just needs to be in the visible paused state until the
// over is removed.
mTargetStack.ensureActivitiesVisibleLocked(mStartActivity, 0, !PRESERVE_WINDOWS);
// Go ahead and tell window manager to execute app transition for this activity
// since the app transition will not be triggered through the resume channel.
mTargetStack.getDisplay().mDisplayContent.executeAppTransition();
} else {
// If the target stack was not previously focusable (previous top running activity
// on that stack was not visible) then any prior calls to move the stack to the
// will not update the focused stack. If starting the new activity now allows the
// task stack to be focusable, then ensure that we now update the focused stack
// accordingly.
if (mTargetStack.isFocusable()
&& !mRootActivityContainer.isTopDisplayFocusedStack(mTargetStack)) {
mTargetStack.moveToFront("startActivityUnchecked");
}
mRootActivityContainer.resumeFocusedStacksTopActivities(
mTargetStack, mStartActivity, mOptions);
}
} else if (mStartActivity != null) {
mSupervisor.mRecentTasks.add(mStartActivity.getTaskRecord());
}
mRootActivityContainer.updateUserStack(mStartActivity.mUserId, mTargetStack);
mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTaskRecord(),
preferredWindowingMode, mPreferredDisplayId, mTargetStack);
return START_SUCCESS;
这里要关注的是startActivityLocked方法, 在这个方法里主要创建了windowToken
final TaskRecord activityTask = r.getTaskRecord();
if (task == activityTask && mTaskHistory.indexOf(task) != (mTaskHistory.size() - 1)) {
mStackSupervisor.mUserLeaving = false;
if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
"startActivity() behind front, mUserLeaving=false");
}
task = activityTask;
// Slot the activity into the history stack and proceed
if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to stack to task " + task,
new RuntimeException("here").fillInStackTrace());
// TODO: Need to investigate if it is okay for the controller to already be created by the
// time we get to this point. I think it is, but need to double check.
// Use test in b/34179495 to trace the call path.
if (r.mAppWindowToken == null) {
r.createAppWindowToken();
}
task.setFrontOfTask();
可以看到windowToken是和appToken所关联的
然后继续往下走,会调用resumeFocusedStacksTopActivities方法
if (mDoResume) {
final ActivityRecord topTaskActivity =
mStartActivity.getTaskRecord().topRunningActivityLocked();
if (!mTargetStack.isFocusable()
|| (topTaskActivity != null && topTaskActivity.mTaskOverlay
&& mStartActivity != topTaskActivity)) {
// If the activity is not focusable, we can't resume it, but still would like to
// make sure it becomes visible as it starts (this will also trigger entry
// animation). An example of this are PIP activities.
// Also, we don't want to resume activities in a task that currently has an overlay
// as the starting activity just needs to be in the visible paused state until the
// over is removed.
mTargetStack.ensureActivitiesVisibleLocked(mStartActivity, 0, !PRESERVE_WINDOWS);
// Go ahead and tell window manager to execute app transition for this activity
// since the app transition will not be triggered through the resume channel.
mTargetStack.getDisplay().mDisplayContent.executeAppTransition();
} else {
// If the target stack was not previously focusable (previous top running activity
// on that stack was not visible) then any prior calls to move the stack to the
// will not update the focused stack. If starting the new activity now allows the
// task stack to be focusable, then ensure that we now update the focused stack
// accordingly.
if (mTargetStack.isFocusable()
&& !mRootActivityContainer.isTopDisplayFocusedStack(mTargetStack)) {
mTargetStack.moveToFront("startActivityUnchecked");
}
mRootActivityContainer.resumeFocusedStacksTopActivities(
mTargetStack, mStartActivity, mOptions);
}
可以看到这个方法上一篇文章也调用过这里走的是不同的case
回顾下上一篇文章,原来的launcherActivity对应的record不为null,但是其stack不是focusable了(当时新的stack已经移到它上面了)
boolean pauseBackStacks(boolean userLeaving, ActivityRecord resuming, boolean dontWait) {
boolean someActivityPaused = false;
for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = mStacks.get(stackNdx);
final ActivityRecord resumedActivity = stack.getResumedActivity();
if (resumedActivity != null
&& (stack.getVisibility(resuming) != STACK_VISIBILITY_VISIBLE
|| !stack.isFocusable())) {
if (DEBUG_STATES) Slog.d(TAG_STATES, "pauseBackStacks: stack=" + stack +
" mResumedActivity=" + resumedActivity);
someActivityPaused |= stack.startPausingLocked(userLeaving, false, resuming,
dontWait);
}
}
return someActivityPaused;
}
而现在显然没有这种情况
接下来看
if (mResumedActivity != null) {
if (DEBUG_STATES) Slog.d(TAG_STATES,
"resumeTopActivityLocked: Pausing " + mResumedActivity);
pausing |= startPausingLocked(userLeaving, false, next, false);
}
由于此activityStack的mResumedActivity不为null,所以还是会走startPausingLocked方法,此方法上篇文章已经分析过了
主要是把此activitystack的 mPausingActivity 和mLastPausedActivity设置为原来的mResumedActivity的值,然后把mResumedActivity设置为null,然后让此activityRecord去执行onPause操作了
至此,startActivityUnchecked方法走完了,并返回了result为0的值
至此一直把这个result返回到startActivityMayWait方法里
if (mRequest.mayWait) {
return startActivityMayWait(mRequest.caller, mRequest.callingUid,
mRequest.callingPackage, mRequest.realCallingPid, mRequest.realCallingUid,
mRequest.intent, mRequest.resolvedType,
mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
mRequest.resultWho, mRequest.requestCode, mRequest.startFlags,
mRequest.profilerInfo, mRequest.waitResult, mRequest.globalConfig,
mRequest.activityOptions, mRequest.ignoreTargetSecurity, mRequest.userId,
mRequest.inTask, mRequest.reason,
mRequest.allowPendingRemoteAnimationRegistryLookup,
mRequest.originatingPendingIntent, mRequest.allowBackgroundActivityStart);
} else {
然后将starter赋值给lastStarter
接下来等客户端paused之后,来通知ams端,来进行相对应的操作
这里和第一篇一样,也是执行了
mRootActivityContainer.resumeFocusedStacksTopActivities(topStack, prev, null);
方法
topStack是相应的activityStack,prev上一个可见的activityRecord也就是Mainactivity
继续分析resumeFocusedStacksTopActivities,这里其activityRecord里的app字段为null,
boolean attachedToProcess() {
return hasProcess() && app.hasThread();
}
所以走到了startSpecificActivityLocked方法中
void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) {
// Is this activity's application already running?
final WindowProcessController wpc =
mService.getProcessController(r.processName, r.info.applicationInfo.uid);
boolean knownToBeDead = false;
if (wpc != null && wpc.hasThread()) {
try {
realStartActivityLocked(r, wpc, 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.
knownToBeDead = true;
}
// Suppress transition until the new activity becomes ready, otherwise the keyguard can
// appear for a short amount of time before the new process with the new activity had the
// ability to set its showWhenLocked flags.
if (getKeyguardController().isKeyguardLocked()) {
r.notifyUnknownVisibilityLaunched();
}
try {
if (Trace.isTagEnabled(TRACE_TAG_ACTIVITY_MANAGER)) {
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "dispatchingStartProcess:"
+ r.processName);
}
// Post message to start process to avoid possible deadlock of calling into AMS with the
// ATMS lock held.
final Message msg = PooledLambda.obtainMessage(
ActivityManagerInternal::startProcess, mService.mAmInternal, r.processName,
r.info.applicationInfo, knownToBeDead, "activity", r.intent.getComponent());
mService.mH.sendMessage(msg);
} finally {
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
}
由于activity.processName对应的WindowProcessController有值,表示有进程存在,因此调用resolveActivity方法
try {
r.startFreezingScreenLocked(proc, 0);
// schedule launch ticks to collect information about slow apps.
r.startLaunchTickingLocked();
r.setProcess(proc);
// Ensure activity is allowed to be resumed after process has set.
if (andResume && !r.canResumeByCompat()) {
andResume = false;
}
这里给其activityRecord赋值process
void setProcess(WindowProcessController proc) {
app = proc;
final ActivityRecord root = task != null ? task.getRootActivity() : null;
if (root == this) {
task.setRootProcess(proc);
}
}
这里判断rootActivity是否是此activityRecord,从而设置task的rootProcess
然后就开始调用LaunchActivityItem开始调用activity的oncreate方法了
final DisplayContent dc = r.getDisplay().mDisplayContent;
clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
System.identityHashCode(r), r.info,
// TODO: Have this take the merged configuration instead of separate global
// and override configs.
mergedConfiguration.getGlobalConfiguration(),
mergedConfiguration.getOverrideConfiguration(), r.compat,
r.launchedFromPackage, task.voiceInteractor, proc.getReportedProcState(),
r.icicle, r.persistentState, results, newIntents,
dc.isNextTransitionForward(), proc.createProfilerInfoIfNeeded(),
r.assistToken));
// Set desired final state.
final ActivityLifecycleItem lifecycleItem;
if (andResume) {
lifecycleItem = ResumeActivityItem.obtain(dc.isNextTransitionForward());
} else {
lifecycleItem = PauseActivityItem.obtain();
}
clientTransaction.setLifecycleStateRequest(lifecycleItem);
// Schedule transaction.
mService.getLifecycleManager().scheduleTransaction(clientTransaction);
这里我们看到把launchActiivtyItem作为clientTransaction的callback,然后又set了一个resume的itemtestActivity
stack.minimalResumeActivityLocked(r);
然后把activityStack的mResumeActivity改成testActivity
最后就和上文一样了
这里附加说一下
public void execute(ClientTransaction transaction) {
if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "Start resolving transaction");
final IBinder token = transaction.getActivityToken();
if (token != null) {
final Map activitiesToBeDestroyed =
mTransactionHandler.getActivitiesToBeDestroyed();
final ClientTransactionItem destroyItem = activitiesToBeDestroyed.get(token);
if (destroyItem != null) {
if (transaction.getLifecycleStateRequest() == destroyItem) {
// It is going to execute the transaction that will destroy activity with the
// token, so the corresponding to-be-destroyed record can be removed.
activitiesToBeDestroyed.remove(token);
}
if (mTransactionHandler.getActivityClient(token) == null) {
// The activity has not been created but has been requested to destroy, so all
// transactions for the token are just like being cancelled.
Slog.w(TAG, tId(transaction) + "Skip pre-destroyed transaction:\n"
+ transactionToString(transaction, mTransactionHandler));
return;
}
}
}
if (DEBUG_RESOLVER) Slog.d(TAG, transactionToString(transaction, mTransactionHandler));
executeCallbacks(transaction);
executeLifecycleState(transaction);
mPendingActions.clear();
if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "End resolving transaction");
}
在TransactionExecutor类的execute方法里可以明显看到先执行的callback,然后在执行execute方法的
private void executeLifecycleState(ClientTransaction transaction) {
final ActivityLifecycleItem lifecycleItem = transaction.getLifecycleStateRequest();
if (lifecycleItem == null) {
// No lifecycle request, return early.
return;
}
final IBinder token = transaction.getActivityToken();
final ActivityClientRecord r = mTransactionHandler.getActivityClient(token);
if (DEBUG_RESOLVER) {
Slog.d(TAG, tId(transaction) + "Resolving lifecycle state: "
+ lifecycleItem + " for activity: "
+ getShortActivityName(token, mTransactionHandler));
}
if (r == null) {
// Ignore requests for non-existent client records for now.
return;
}
// Cycle to the state right before the final requested state.
cycleToPath(r, lifecycleItem.getTargetState(), true /* excludeLastState */, transaction);
// Execute the final transition with proper parameters.
lifecycleItem.execute(mTransactionHandler, token, mPendingActions);
lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions);
}
可能有人会疑惑为啥没执行onStart方法
其实这个方法是连带着onCreate方法一起执行的
private void performLifecycleSequence(ActivityClientRecord r, IntArray path,
ClientTransaction transaction) {
final int size = path.size();
for (int i = 0, state; i < size; i++) {
state = path.get(i);
if (DEBUG_RESOLVER) {
Slog.d(TAG, tId(transaction) + "Transitioning activity: "
+ getShortActivityName(r.token, mTransactionHandler)
+ " to state: " + getStateName(state));
}
switch (state) {
case ON_CREATE:
mTransactionHandler.handleLaunchActivity(r, mPendingActions,
null /* customIntent */);
break;
case ON_START:
mTransactionHandler.handleStartActivity(r, mPendingActions);
break;
cycleToPath方法间接会调用performLifecycleSequence方法,从而执行onStart