美文网首页
基于10.0的activity分析(二)

基于10.0的activity分析(二)

作者: 暴走的小青春 | 来源:发表于2020-07-23 15:04 被阅读0次

    本文主要分析
    从当前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<IBinder, ClientTransactionItem> 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

    相关文章

      网友评论

          本文标题:基于10.0的activity分析(二)

          本文链接:https://www.haomeiwen.com/subject/biwzkktx.html