当前位置: 首页 > news >正文

Activity的finish()流程

目录

1.概述

2.生命周期方法

3. pause流程

3.1 Activity.finish

3.2 ActivityClientController.finishActivity

3.3 ActivityRecord.finishIfPossible

3.4 TaskFragment.startPausing

3.5 TaskFragment.schedulePauseActivity

3.6 ClientLifecycleManager.scheduleTransaction

3.7 ApplicationThread.scheduleTransaction

3.8 TransactionExecutor.execute

3.9 PauseActivityItem.execute

3.10 ActivityThread.handlePauseActivity

3.11 Activity.performPause

4.stop/destory流程

4.1 ActivityThread.handleResumeActivity

4.2 ActivityThread.Idle.queueIdle

4.3 ActivityTaskSupervisor.activityIdleInternal

4.3.1 IDLE_TIMEOUT_MSG

4.3.2 processStoppingAndFinishingActivities


1.概述

    在Android中,我们可以通过调用finish()方法来结束一个Activity,调用这个方法后,Activity对应的生命周期方法会被调用、所在的Task也会发生变化。本文主要通过分析Activity的finish流程来了解Activity的结束时生命周期及Task变化,代码基于Android 14。

2.生命周期方法

先来看下Activity各个生命周期方法的特点

  • onCreate

Activity第一次创建时被调用,只会被调用一次,通常用于初始化和布局设置,这时候Activity还是不可见状态。

  • onStart

Activity由不可见变为可见状态,但是未获得焦点,处于不可交互状态,用户无法操作 UI。

  • onResume

Activity开始处于前台,用户可以交互,此时Activity的UI可操作并完全可见。

  • onPause

和onResume()方法对应,Activity开始进入后台,处于不可交互、焦点丢失状态。

  • onStop

和onStart()方法对应,Activity开始不可见。

  • onRestart

Activity从后台返回到前台时调用,一般是从onStop()状态重新回到可见状态时调用,可以在此方法中进行恢复性操作,如恢复资源、重启动画等。

  • onDestory

Activity即将被销毁时调用,该方法是Activity生命周期中的最后一个方法,被调用后活动对象将被销毁,且无法恢复

3. pause流程

从Activity.finish()方法开始分析,通过调用finish()方法可以结束某个Activity。

3.1 Activity.finish
frameworks/base/core/java/android/app/Activity.javapublic void finish() {finish(DONT_FINISH_TASK_WITH_ACTIVITY);}

调用内部finish()方法并传入DONT_FINISH_TASK_WITH_ACTIVITY值作为参数,这个值表示在结束当前Activity时,不结束其所在的任务(Task),类似的值还有:

DONT_FINISH_TASK_WITH_ACTIVITY:结束Activity时,不会销毁Activity所在的任务栈(Task)。

FINISH_TASK_WITH_ROOT_ACTIVITY:如果待finish的Activity是所在任务栈的根Activity,则需要销毁所在任务栈。

FINISH_TASK_WITH_ACTIVITY:结束Activity时,会销毁Activity所在的任务栈(Task)。

继续看finish方法:

frameworks/base/core/java/android/app/Activity.javaprivate void finish(int finishTask) {if (mParent == null) {//一般情况下都会走到这里int resultCode;Intent resultData;synchronized (this) {resultCode = mResultCode;resultData = mResultData;}if (false) Log.v(TAG, "Finishing self: token=" + mToken);if (resultData != null) {resultData.prepareToLeaveProcess(this);}if (ActivityClient.getInstance().finishActivity(mToken, resultCode, resultData,finishTask)) {//调用ActivityClient里的finishActivity方法mFinished = true;}} else {mParent.finishFromChild(this);}getAutofillClientController().onActivityFinish(mIntent);//设置回调}

首先判断当前Activity是否有父活动mParent,一般情况下没有。

接着调用ActivityClient.getInstance().finishActivity() 来结束当前Activity,如果 finishActivity 返回 true,表示活动已成功结束,mFinished 标志被设置为 true。

ActivityClient.finishActivity()方法里最终通过binder调用ActivityClientController里的finishActivity()方法。

3.2 ActivityClientController.finishActivity
frameworks/base/services/core/java/com/android/server/wm/ActivityClientController.java/*** This is the internal entry point for handling Activity.finish().** @param token      The Binder token referencing the Activity we want to finish.* @param resultCode Result code, if any, from this Activity.* @param resultData Result data (Intent), if any, from this Activity.* @param finishTask Whether to finish the task associated with this Activity.* @return Returns true if the activity successfully finished, or false if it is still running.*/@Overridepublic boolean finishActivity(IBinder token, int resultCode, Intent resultData,int finishTask) {// Refuse possible leaked file descriptors.if (resultData != null && resultData.hasFileDescriptors()) {//为了防止文件描述符泄漏到其他进程,resultData不允许携带文件描述符throw new IllegalArgumentException("File descriptors passed in Intent");}final ActivityRecord r;synchronized (mGlobalLock) {r = ActivityRecord.isInRootTaskLocked(token);//查找与传入的token相关的ActivityRecord。if (r == null) {//没有找到该活动,表示活动已经结束或不存在,直接返回truereturn true;}}// Carefully collect grants without holding lock.final NeededUriGrants resultGrants = mService.collectGrants(resultData, r.resultTo);//收集URI权限synchronized (mGlobalLock) {// Check again in case activity was removed when collecting grants.if (!r.isInHistory()) {//如果活动已经不在历史堆栈中,则返回true,表示活动已经结束。return true;}// Keep track of the root activity of the task before we finish it.final Task tr = r.getTask();//获取当前活动所在Taskfinal ActivityRecord rootR = tr.getRootActivity();//获取当前活动所在Task的rootActivityif (rootR == null) {Slog.w(TAG, "Finishing task with all activities already finished");}// Do not allow task to finish if last task in lockTask mode. Launchable priv-apps can// finish.if (mService.getLockTaskController().activityBlockedFromFinish(r)) {//不允许finish该Activityreturn false;}// TODO: There is a dup. of this block of code in ActivityStack.navigateUpToLocked// We should consolidate.if (mService.mController != null) {// Find the first activity that is not finishing.final ActivityRecord next =r.getRootTask().topRunningActivity(token, INVALID_TASK_ID);//获取当前任务栈中正在运行的顶部Activityif (next != null) {// ask watcher if this is allowedboolean resumeOK = true;try {resumeOK = mService.mController.activityResuming(next.packageName);//是否允许继续结束当前Activity} catch (RemoteException e) {mService.mController = null;Watchdog.getInstance().setActivityController(null);}if (!resumeOK) {//不允许,直接返回falseSlog.i(TAG, "Not finishing activity because controller resumed");return false;}}}// Note down that the process has finished an activity and is in background activity// starts grace period.if (r.app != null) {r.app.setLastActivityFinishTimeIfNeeded(SystemClock.uptimeMillis());//设置Activity结束时间}final long origId = Binder.clearCallingIdentity();Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "finishActivity");try {final boolean res;final boolean finishWithRootActivity =finishTask == Activity.FINISH_TASK_WITH_ROOT_ACTIVITY;//当前传入的不是这个值,所以为falsemTaskSupervisor.getBackgroundActivityLaunchController().onActivityRequestedFinishing(r);if (finishTask == Activity.FINISH_TASK_WITH_ACTIVITY|| (finishWithRootActivity && r == rootR)) {//在结束Activity的同时结束它所属的task// If requested, remove the task that is associated to this activity only if it// was the root activity in the task. The result code and data is ignored// because we don't support returning them across task boundaries. Also, to// keep backwards compatibility we remove the task from recents when finishing// task with root activity.mTaskSupervisor.removeTask(tr, false /*killProcess*/,finishWithRootActivity, "finish-activity", r.getUid(), r.getPid(),r.info.name);//销毁Taskres = true;// Explicitly dismissing the activity so reset its relaunch flag.r.mRelaunchReason = RELAUNCH_REASON_NONE;} else {//由上文可知,传入的参数是DONT_FINISH_TASK_WITH_ACTIVITY,会走到这里r.finishIfPossible(resultCode, resultData, resultGrants, "app-request",true /* oomAdj */);res = r.finishing;if (!res) {Slog.i(TAG, "Failed to finish by app-request");}}return res;} finally {Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);Binder.restoreCallingIdentity(origId);}}}

先检查一些权限和Activity是否存在,接着判断当前条件下是否允许结束Activity,如果不允许,则直接返回false。

最后,如果传递的参数是FINISH_TASK_WITH_ROOT_ACTIVITY或者当前活动是rootActivity,调用removeTask()方法将与该活动关联的任务移除;

否则通过 finishIfPossible() 结束该活动,由上文可以传递的参数是DONT_FINISH_TASK_WITH_ACTIVITY,所以调用的是ActivityRecord.finishIfPossible()方法。

3.3 ActivityRecord.finishIfPossible
frameworks/base/services/core/java/com/android/server/wm/ActivityRecord.java
@FinishRequest int finishIfPossible(int resultCode, Intent resultData,NeededUriGrants resultGrants, String reason, boolean oomAdj) {ProtoLog.v(WM_DEBUG_STATES, "Finishing activity r=%s, result=%d, data=%s, "+ "reason=%s", this, resultCode, resultData, reason);if (finishing) {//当前Activity已经处于finish状态Slog.w(TAG, "Duplicate finish request for r=" + this);return FINISH_RESULT_CANCELLED;//不重复finish}if (!isInRootTaskLocked()) {//当前活动是否处于根task中Slog.w(TAG, "Finish request when not in root task for r=" + this);return FINISH_RESULT_CANCELLED;}final Task rootTask = getRootTask();//获取root taskfinal boolean mayAdjustTop = (isState(RESUMED) || rootTask.getTopResumedActivity() == null)&& rootTask.isFocusedRootTaskOnDisplay()// Do not adjust focus task because the task will be reused to launch new activity.&& !task.isClearingToReuseTask();//如果当前活动处于RESUMED状态、根任务的栈顶活动为空且任务是当前焦点任务并且没有正在清除任务,则可以调整任务的焦点final boolean shouldAdjustGlobalFocus = mayAdjustTop// It must be checked before {@link #makeFinishingLocked} is called, because a// root task is not visible if it only contains finishing activities.&& mRootWindowContainer.isTopDisplayFocusedRootTask(rootTask);//是否需要调整全局焦点mAtmService.deferWindowLayout();//暂时延迟窗口布局更新try {mTaskSupervisor.mNoHistoryActivities.remove(this);//从mNoHistoryActivities列表中移除当前活动makeFinishingLocked();//标记当前活动正在结束,在这里finishing被设置为true// Make a local reference to its task since this.task could be set to null once this// activity is destroyed and detached from task.final Task task = getTask();EventLogTags.writeWmFinishActivity(mUserId, System.identityHashCode(this),task.mTaskId, shortComponentName, reason);//wm_finish_activity打印的地方ActivityRecord next = task.getActivityAbove(this);//获取当前Activity之上的Activity,即当前Activity所在任务栈中的下一个Activityif (next != null) {//如果当前活动的Intent中包含 FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET标志,则将其传递给下一个活动,指示当任务重置时清除该活动if ((intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {// If the caller asked that this activity (and all above it)// be cleared when the task is reset, don't lose that information,// but propagate it up to the next activity.next.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);}}pauseKeyDispatchingLocked();//停止分发按键// We are finishing the top focused activity and its task has nothing to be focused so// the next focusable task should be focused.if (mayAdjustTop && task.topRunningActivity(true /* focusableOnly */)== null) {//如果活动是栈顶并且没有可用的活动,调整焦点到下一个可以获得焦点的tasktask.adjustFocusToNextFocusableTask("finish-top", false /* allowFocusSelf */,shouldAdjustGlobalFocus);}finishActivityResults(resultCode, resultData, resultGrants);//处理返回的结果和授权,完成活动结束的结果设置final boolean endTask = task.getTopNonFinishingActivity() == null&& !task.isClearingToReuseTask();final WindowContainer<?> trigger = endTask ? task : this;final Transition newTransition =mTransitionController.requestCloseTransitionIfNeeded(trigger);//关闭过渡动画if (newTransition != null) {newTransition.collectClose(trigger);} else if (mTransitionController.isCollecting()) {mTransitionController.getCollectingTransition().collectClose(trigger);}if (isState(RESUMED)) {//如果当前Activity处于resume状态if (endTask) {mAtmService.getTaskChangeNotificationController().notifyTaskRemovalStarted(task.getTaskInfo());}// Prepare app close transition, but don't execute just yet. It is possible that// an activity that will be made resumed in place of this one will immediately// launch another new activity. In this case current closing transition will be// combined with open transition for the new activity.if (DEBUG_VISIBILITY || DEBUG_TRANSITION) {Slog.v(TAG_TRANSITION, "Prepare close transition: finishing " + this);}mDisplayContent.prepareAppTransition(TRANSIT_CLOSE);//准备结束过渡动画// When finishing the activity preemptively take the snapshot before the app window// is marked as hidden and any configuration changes take place// Note that RecentsAnimation will handle task snapshot while switching apps with// the best capture timing (e.g. IME window capture),// No need additional task capture while task is controlled by RecentsAnimation.if (!mTransitionController.isShellTransitionsEnabled()&& !task.isAnimatingByRecents()) {final ArraySet<Task> tasks = Sets.newArraySet(task);mAtmService.mWindowManager.mTaskSnapshotController.snapshotTasks(tasks);mAtmService.mWindowManager.mTaskSnapshotController.addSkipClosingAppSnapshotTasks(tasks);}// Tell window manager to prepare for this one to be removed.setVisibility(false);//设置当前Activity不可见// Propagate the last IME visibility in the same task, so the IME can show// automatically if the next activity has a focused editable view.if (mLastImeShown && mTransitionController.isShellTransitionsEnabled()) {final ActivityRecord nextRunning = task.topRunningActivity();if (nextRunning != null) {nextRunning.mLastImeShown = true;}}if (getTaskFragment().getPausingActivity() == null) {ProtoLog.v(WM_DEBUG_STATES, "Finish needs to pause: %s", this);if (DEBUG_USER_LEAVING) {Slog.v(TAG_USER_LEAVING, "finish() => pause with userLeaving=false");}getTaskFragment().startPausing(false /* userLeaving */, false /* uiSleeping */,null /* resuming */, "finish");//开始执行pause方法}if (endTask) {mAtmService.getLockTaskController().clearLockedTask(task);// This activity was in the top focused root task and this is the last// activity in that task, give this activity a higher layer so it can stay on// top before the closing task transition be executed.if (mayAdjustTop) {mNeedsZBoost = true;mDisplayContent.assignWindowLayers(false /* setLayoutNeeded */);}}} else if (!isState(PAUSING)) {//如果当前活动不处于PAUSING状态if (mVisibleRequested) {// Prepare and execute close transition.if (mTransitionController.isShellTransitionsEnabled()) {setVisibility(false);if (newTransition != null) {// This is a transition specifically for this close operation, so set// ready now.newTransition.setReady(mDisplayContent, true);}} else {prepareActivityHideTransitionAnimation();}}final boolean removedActivity = completeFinishing("finishIfPossible") == null;// Performance optimization - only invoke OOM adjustment if the state changed to// 'STOPPING'. Otherwise it will not change the OOM scores.if (oomAdj && isState(STOPPING)) {mAtmService.updateOomAdj();//更新 OOM}// The following code is an optimization. When the last non-task overlay activity// is removed from the task, we remove the entire task from the root task. However,// since that is done after the scheduled destroy callback from the activity, that// call to change the visibility of the task overlay activities would be out of// sync with the activity visibility being set for this finishing activity above.// In this case, we can set the visibility of all the task overlay activities when// we detect the last one is finishing to keep them in sync.if (task.onlyHasTaskOverlayActivities(false /* includeFinishing */)) {task.forAllActivities((r) -> {r.prepareActivityHideTransitionAnimationIfOvarlay();});}return removedActivity ? FINISH_RESULT_REMOVED : FINISH_RESULT_REQUESTED;} else {ProtoLog.v(WM_DEBUG_STATES, "Finish waiting for pause of: %s", this);}return FINISH_RESULT_REQUESTED;} finally {mAtmService.continueWindowLayout();}}

对当前Activity的焦点、Task、可见性进行调整,setVisibility(false)设置当前Activity不可见。wm_finish_activity日志也是在这里打印。

主要看TaskFragment.startPausing方法去pause当前Activity,无论是Activity之间的跳转还是直接finish Actiivty,最先调用的生命周期方法都是onPause()。

3.4 TaskFragment.startPausing
frameworks/base/services/core/java/com/android/server/wm/TaskFragment.javaboolean startPausing(boolean userLeaving, boolean uiSleeping, ActivityRecord resuming,String reason) {if (!hasDirectChildActivities()) {//如果Activity没有直接子活动,则跳过pause操作,返回falsereturn false;}ProtoLog.d(WM_DEBUG_STATES, "startPausing: taskFrag =%s " + "mResumedActivity=%s", this,mResumedActivity);if (mPausingActivity != null) {//如果有处于pausing状态的ActivitySlog.wtf(TAG, "Going to pause when pause is already pending for " + mPausingActivity+ " state=" + mPausingActivity.getState());if (!shouldSleepActivities()) {//是否应该让活动进入休眠状态,比方说系统休眠或者屏幕关闭的情况下// Avoid recursion among check for sleep and complete pause during sleeping.// Because activity will be paused immediately after resume, just let pause// be completed by the order of activity paused from clients.completePause(false, resuming);//完成pause操作}}ActivityRecord prev = mResumedActivity;//prev为当前活动if (prev == null) {if (resuming == null) {//没有活动处于resume状态Slog.wtf(TAG, "Trying to pause when nothing is resumed");mRootWindowContainer.resumeFocusedTasksTopActivities();}return false;}if (prev == resuming) {//如果当前活动正处于resuming状态,避免在resume过程中pause当前ActivitySlog.wtf(TAG, "Trying to pause activity that is in process of being resumed");return false;}ProtoLog.v(WM_DEBUG_STATES, "Moving to PAUSING: %s", prev);mPausingActivity = prev;//将当前活动prev设置为正在暂停的活动mLastPausedActivity = prev;if (!prev.finishing && prev.isNoHistory()&& !mTaskSupervisor.mNoHistoryActivities.contains(prev)) {//如果活动不是finishing状态且具有noHistory标记(即不应保存历史记录),它会被添加到mNoHistoryActivities列表中mTaskSupervisor.mNoHistoryActivities.add(prev);}prev.setState(PAUSING, "startPausingLocked");//更新状态为PAUSINGprev.getTask().touchActiveTime();mAtmService.updateCpuStats();boolean pauseImmediately = false;//是否立刻pauseboolean shouldAutoPip = false;//是否应该自动进入Pip画中画模式if (resuming != null) {//如果存在正在resume的Activity,处理Pip相关逻辑// We do not want to trigger auto-PiP upon launch of a translucent activity.final boolean resumingOccludesParent = resuming.occludesParent();// Resuming the new resume activity only if the previous activity can't go into Pip// since we want to give Pip activities a chance to enter Pip before resuming the// next activity.final boolean lastResumedCanPip = prev.checkEnterPictureInPictureState("shouldAutoPipWhilePausing", userLeaving);if (userLeaving && resumingOccludesParent && lastResumedCanPip&& prev.pictureInPictureArgs.isAutoEnterEnabled()) {shouldAutoPip = true;} else if (!lastResumedCanPip) {// If the flag RESUME_WHILE_PAUSING is set, then continue to schedule the previous// activity to be paused.pauseImmediately = (resuming.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0;} else {// The previous activity may still enter PIP even though it did not allow auto-PIP.}}if (prev.attachedToProcess()) {//Activity是否附加到进程,pause的Activity一般都是已经打开过的,所以进程存在if (shouldAutoPip) {//Pip相关prev.mPauseSchedulePendingForPip = true;boolean didAutoPip = mAtmService.enterPictureInPictureMode(prev, prev.pictureInPictureArgs, false /* fromClient */);ProtoLog.d(WM_DEBUG_STATES, "Auto-PIP allowed, entering PIP mode "+ "directly: %s, didAutoPip: %b", prev, didAutoPip);} else {//pause活动schedulePauseActivity(prev, userLeaving, pauseImmediately,false /* autoEnteringPip */, reason);}} else {//如果活动没有附加到进程,则清除暂停状态并从mNoHistoryActivities列表中移除该活动mPausingActivity = null;mLastPausedActivity = null;mTaskSupervisor.mNoHistoryActivities.remove(prev);}// If we are not going to sleep, we want to ensure the device is// awake until the next activity is started.if (!uiSleeping && !mAtmService.isSleepingOrShuttingDownLocked()) {mTaskSupervisor.acquireLaunchWakelock();}// If already entered PIP mode, no need to keep pausing.if (mPausingActivity != null) {// Have the window manager pause its key dispatching until the new// activity has started.  If we're pausing the activity just because// the screen is being turned off and the UI is sleeping, don't interrupt// key dispatch; the same activity will pick it up again on wakeup.if (!uiSleeping) {prev.pauseKeyDispatchingLocked();//暂停键盘事件的分发,避免在活动暂停过程中出现干扰。} else {ProtoLog.v(WM_DEBUG_STATES, "Key dispatch not paused for screen off");}if (pauseImmediately) {// If the caller said they don't want to wait for the pause, then complete// the pause now.completePause(false, resuming);//立即完成pausereturn false;} else {//否则,安排一个500ms的pause超时prev.schedulePauseTimeout();// All activities will be stopped when sleeping, don't need to wait for pause.if (!uiSleeping) {// Unset readiness since we now need to wait until this pause is complete.mTransitionController.setReady(this, false /* ready */);}return true;}} else {// This activity either failed to schedule the pause or it entered PIP mode,// so just treat it as being paused now.ProtoLog.v(WM_DEBUG_STATES, "Activity not running or entered PiP, resuming next.");if (resuming == null) {mRootWindowContainer.resumeFocusedTasksTopActivities();}return false;}}

核心方法是schedulePauseActivity

3.5 TaskFragment.schedulePauseActivity
    void schedulePauseActivity(ActivityRecord prev, boolean userLeaving,boolean pauseImmediately, boolean autoEnteringPip, String reason) {ProtoLog.v(WM_DEBUG_STATES, "Enqueueing pending pause: %s", prev);try {prev.mPauseSchedulePendingForPip = false;//将活动的mPauseSchedulePendingForPip标志重置为 false,意味着活动不再等待进入画中画(PIP)模式的暂停EventLogTags.writeWmPauseActivity(prev.mUserId, System.identityHashCode(prev),prev.shortComponentName, "userLeaving=" + userLeaving, reason);//wm_pause_activity event log打印的地方mAtmService.getLifecycleManager().scheduleTransaction(prev.app.getThread(),prev.token, PauseActivityItem.obtain(prev.finishing, userLeaving,prev.configChangeFlags, pauseImmediately, autoEnteringPip));//binder通知当前Activity的进程执行pause操作} catch (Exception e) {// Ignore exception, if process died other code will cleanup.Slog.w(TAG, "Exception thrown during pause", e);mPausingActivity = null;mLastPausedActivity = null;mTaskSupervisor.mNoHistoryActivities.remove(prev);}}

在这里会打印我们常见的wm_pause_activity日志。

getLifecycleManager()获取到的是ClientLifecycleManager实例,这个类是负责管理Activity生命周期的,这里传入PauseActivityItem给ClientLifecycleManager用来执行pause操作,类似的item还有StopActivityItem、StartActivityItem、DestroyActivityItem、ResumeActivityItem等,不同的item用来执行不同的生命周期。

3.6 ClientLifecycleManager.scheduleTransaction
frameworks/base/services/core/java/com/android/server/wm/ClientLifecycleManager.javavoid scheduleTransaction(ClientTransaction transaction) throws RemoteException {final IApplicationThread client = transaction.getClient();transaction.schedule();//调用ClientTransaction的schedule()方法if (!(client instanceof Binder)) {// If client is not an instance of Binder - it's a remote call and at this point it is// safe to recycle the object. All objects used for local calls will be recycled after// the transaction is executed on client in ActivityThread.transaction.recycle();}}

主要是调用ClientTransaction的schedule()方法

frameworks/base/core/java/android/app/servertransaction/ClientTransaction.javapublic void schedule() throws RemoteException {mClient.scheduleTransaction(this);//binder调用ApplicationThread的scheduleTransaction()方法}private IApplicationThread mClient;

实际上是通过binder调用ApplicationThread的scheduleTransaction()方法。

3.7 ApplicationThread.scheduleTransaction
frameworks/base/core/java/android/app/ActivityThread.java@Overridepublic void scheduleTransaction(ClientTransaction transaction) throws RemoteException {ActivityThread.this.scheduleTransaction(transaction);//调用ActivityThread的同名方法}public final class ActivityThread extends ClientTransactionHandler

调用ActivityThread的同名方法,但是ActivityThread并没有实现scheduleTransaction()方法,不过ActiivtyThread继承了ClientTransactionHandler类,实际上scheduleTransaction()是在ClientTransactionHandler里实现的。

frameworks/base/core/java/android/app/ClientTransactionHandler.javavoid scheduleTransaction(ClientTransaction transaction) {transaction.preExecute(this);sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);}frameworks/base/core/java/android/app/ActivityThread.javacase EXECUTE_TRANSACTION:final ClientTransaction transaction = (ClientTransaction) msg.obj;mTransactionExecutor.execute(transaction);if (isSystem()) {// Client transactions inside system process are recycled on the client side// instead of ClientLifecycleManager to avoid being cleared before this// message is handled.transaction.recycle();}// TODO(lifecycler): Recycle locally scheduled transactions.break;

先发送一个EXECUTE_TRANSACTION的message,实际处理在ActivityThread。消息处理的地方调用了TransactionExecutor.execute方法。

3.8 TransactionExecutor.execute
frameworks/base/core/java/android/app/servertransaction/TransactionExecutor.javapublic void execute(ClientTransaction transaction) {......executeCallbacks(transaction);//处理与该事务相关的回调executeLifecycleState(transaction);//触发活动的生命周期状态如:pause、resume、stop等......}/** Transition to the final state if requested by the transaction. */private void executeLifecycleState(ClientTransaction transaction) {final ActivityLifecycleItem lifecycleItem = transaction.getLifecycleStateRequest();//获取 ActivityLifecycleItem,它包含了一个生命周期状态请求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);//调用ActivityLifecycleItem的execute方法lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions);//调用ActivityLifecycleItem的postExecute方法}

executeLifecycleState()方法触发活动的生命周期,首先通过getLifecycleStateRequest获取生命周期请求ActivityLifecycleItem,然后分别调用ActivityLifecycleItem的execute和postExecute方法。

先来看下getLifecycleStateRequest:

frameworks/base/core/java/android/app/servertransaction/ClientTransaction.javapublic ActivityLifecycleItem getLifecycleStateRequest() {return mLifecycleStateRequest;}/*** Set the lifecycle state in which the client should be after executing the transaction.* @param stateRequest A lifecycle request initialized with right parameters.*/public void setLifecycleStateRequest(ActivityLifecycleItem stateRequest) {mLifecycleStateRequest = stateRequest;}

mLifecycleStateRequest是通过setLifecycleStateRequest()方法设置的,那么这个值是什么时候被设置的呢?回过头来看schedulePauseActivity()方法:

frameworks/base/services/core/java/com/android/server/wm/TaskFragment.javavoid schedulePauseActivity(ActivityRecord prev, boolean userLeaving,boolean pauseImmediately, boolean autoEnteringPip, String reason) {......mAtmService.getLifecycleManager().scheduleTransaction(prev.app.getThread(),prev.token, PauseActivityItem.obtain(prev.finishing, userLeaving,prev.configChangeFlags, pauseImmediately, autoEnteringPip));} ......}//调用ClientLifecycleManager.java里的三参函数
frameworks/base/services/core/java/com/android/server/wm/ClientLifecycleManager.javavoid scheduleTransaction(@NonNull IApplicationThread client, @NonNull IBinder activityToken,@NonNull ActivityLifecycleItem stateRequest) throws RemoteException {final ClientTransaction clientTransaction = transactionWithState(client, activityToken,stateRequest);scheduleTransaction(clientTransaction);}//通过transactionWithState()设置clientTransactionprivate static ClientTransaction transactionWithState(@NonNull IApplicationThread client,@NonNull IBinder activityToken, @NonNull ActivityLifecycleItem stateRequest) {final ClientTransaction clientTransaction = ClientTransaction.obtain(client, activityToken);clientTransaction.setLifecycleStateRequest(stateRequest);return clientTransaction;}frameworks/base/core/java/android/app/servertransaction/PauseActivityItem.java
public class PauseActivityItem extends ActivityLifecycleItem {.....public static PauseActivityItem obtain(boolean finished, boolean userLeaving, int configChanges,boolean dontReport, boolean autoEnteringPip) {PauseActivityItem instance = ObjectPool.obtain(PauseActivityItem.class);if (instance == null) {instance = new PauseActivityItem();}instance.mFinished = finished;instance.mUserLeaving = userLeaving;instance.mConfigChanges = configChanges;instance.mDontReport = dontReport;instance.mAutoEnteringPip = autoEnteringPip;return instance;}

可以看出setLifecycleStateRequest()是在transactionWithState()方法里调用的,stateRequest参数就是上面传下来的PauseActivityItem对象。

所以实际上会调用PauseActivityItem的execute和postExecute方法,其他生命周期方法也是类似的逻辑。

3.9 PauseActivityItem.execute
frameworks/base/core/java/android/app/servertransaction/PauseActivityItem.javapublic void execute(ClientTransactionHandler client, ActivityClientRecord r,PendingTransactionActions pendingActions) {Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityPause");client.handlePauseActivity(r, mFinished, mUserLeaving, mConfigChanges, mAutoEnteringPip,pendingActions, "PAUSE_ACTIVITY_ITEM");Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);}

调用ClientTransactionHandler的handlePauseActivity()方法处理Activity的pause操作,ClientTransactionHandler是一个抽象类,它内部的方法实现实际上在ActivityThread里

3.10 ActivityThread.handlePauseActivity
frameworks/base/core/java/android/app/ActivityThread.javapublic void handlePauseActivity(ActivityClientRecord r, boolean finished, boolean userLeaving,int configChanges, boolean autoEnteringPip, PendingTransactionActions pendingActions,String reason) {......performPauseActivity(r, finished, reason, pendingActions);......mSomeActivitiesChanged = true;}

继续调用performPauseActivity()方法

    final Bundle performPauseActivity(IBinder token, boolean finished, String reason,PendingTransactionActions pendingActions) {ActivityClientRecord r = mActivities.get(token);//根据token查找ActivityClientRecordreturn r != null ? performPauseActivity(r, finished, reason, pendingActions) : null;}/*** Pause the activity.* @return Saved instance state for pre-Honeycomb apps if it was saved, {@code null} otherwise.*/private Bundle performPauseActivity(ActivityClientRecord r, boolean finished, String reason,PendingTransactionActions pendingActions) {if (r.paused) {//活动是否已经暂停if (r.activity.mFinished) {//活动也已经结束// If we are finishing, we won't call onResume() in certain cases.// So here we likewise don't want to call onPause() if the activity// isn't resumed.return null;//不再重复调用onPause方法,直接返回}RuntimeException e = new RuntimeException("Performing pause of activity that is not resumed: "+ r.intent.getComponent().toShortString());Slog.e(TAG, e.getMessage(), e);}......performPauseActivityIfNeeded(r, reason);//执行pause操作,包括暂停活动的 UI 线程、保存数据、更新系统状态等......return shouldSaveState ? r.state : null;}

继续调用performPauseActivityIfNeeded()方法处理Activity的pause操作

    private void performPauseActivityIfNeeded(ActivityClientRecord r, String reason) {if (r.paused) {//活动已经paused,直接返回// You are already paused silly...return;}// Always reporting top resumed position loss when pausing an activity. If necessary, it// will be restored in performResumeActivity().reportTopResumedActivityChanged(r, false /* onTop */, "pausing");try {r.activity.mCalled = false;mInstrumentation.callActivityOnPause(r.activity);//调用Activity的onPause方法if (!r.activity.mCalled) {//如果mCalled为false,说明onPause()方法没有正确地通过 super.onPause()调用,抛出SuperNotCalledException异常throw new SuperNotCalledException("Activity " + safeToComponentShortString(r.intent)+ " did not call through to super.onPause()");}} catch (SuperNotCalledException e) {throw e;} catch (Exception e) {if (!mInstrumentation.onException(r.activity, e)) {throw new RuntimeException("Unable to pause activity "+ safeToComponentShortString(r.intent) + ": " + e.toString(), e);}}r.setState(ON_PAUSE);//设置状态为ON_PAUSE,表示活动已经进入暂停状态}

通过Instrumentation.callActivityOnPause()方法调用Activity的onPause方法

frameworks/base/core/java/android/app/Instrumentation.javapublic void callActivityOnPause(Activity activity) {activity.performPause();}

调用Activity的performPause()方法

3.11 Activity.performPause
frameworks/base/core/java/android/app/Activity.javafinal void performPause() {if (Trace.isTagEnabled(Trace.TRACE_TAG_WINDOW_MANAGER)) {Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "performPause:"+ mComponent.getClassName());}dispatchActivityPrePaused();//通知与当前活动相关的各个组件,当前活动即将进入暂停状态mDoReportFullyDrawn = false;mFragments.dispatchPause();//通知与该活动相关的所有Fragments进行暂停操作,来确保Fragments在活动暂停时能执行相应的生命周期方法mCalled = false;//用于检查是否已经调用了super.onPause()final long startTime = SystemClock.uptimeMillis();//记录当前时间onPause();//调用当前活动的 onPause() 方法final long duration = SystemClock.uptimeMillis() - startTime;//onPause()方法的执行时长EventLogTags.writeWmOnPausedCalled(mIdent, getComponentName().getClassName(),"performPause", duration);//wm_on_paused_called log打印的地方mResumed = false;//onResume()方法已经调用,Activity不再处于resume状态if (!mCalled && getApplicationInfo().targetSdkVersion>= android.os.Build.VERSION_CODES.GINGERBREAD) {throw new SuperNotCalledException("Activity " + mComponent.toShortString() +" did not call through to super.onPause()");}dispatchActivityPostPaused();//活动暂停后通知其他模块或组件Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);}

调用dispatchActivityPrePaused通知Activity相关的其他组件,当前Activity即将进入pause操作;接着调用Fragments.dispatchPause方法通知Fragment进行pause操作;然后onPause()调用当前Actiivty的onPause方法并记录方法耗时时间;最后调用dispatchActivityPostPaused方法在活动暂停后通知其他模块或组件。

到这里Activity的pause流程就执行完了,但是stop/destory操作是什么时候执行的呢?下面继续来分析Activity的stop/destory流程。

4.stop/destory流程

    在activity跳转过程中,上一个Activity执行pause操作之后并不会立即执行stop操作,而是会先执行下一个Activity的create->start-resume,然后才会执行上一个Activity的stop/destory。所以Activity的stop/destory执行时机具有不确定性。上文我们分析了finish流程之后,也没看到哪里执行了stop/destory操作。

刚刚提到,下一个Activity执行resume操作之后,才会执行上一个Activity的stop/destory操作,那么就先从Activity的resume操作开始分析。

Activity的resume操作从ActivityThread.handleResumeActivity开始:

4.1 ActivityThread.handleResumeActivity
frameworks/base/core/java/android/app/ActivityThread.java
public void handleResumeActivity(ActivityClientRecord r, boolean finalStateRequest,boolean isForward, boolean shouldSendCompatFakeFocus, String reason) {......if (localLOGV) Slog.v(TAG, "Scheduling idle handler for " + r);Looper.myQueue().addIdleHandler(new Idler());}

handleResumeActivity方法主要处理Activity的resume操作。它会在Activity resume时执行一系列操作,包括窗口管理、界面更新、生命周期回调等,最后添加IdleHandler空闲消息机制。

‌IdleHandler‌是Android中MessageQueue的一个接口,主要用于在主线程空闲时执行一些任务,stop/destory就是通过它来实现的。

所以,当下一个Activity执行完resume方法,完成UI绘制之后,主线程空闲,就开始通过IdleHandler去调用上一个Activity的sop/destory操作。

在android 11 Handler消息机制-CSDN博客里提到过当在MessageQueue队列里没有需要立即执行的任务时,如果有IdleHandler消息则会去执行IdleHandler的任务,通过idler.queueIdle()处理任务。

先来看下IdelHandler:

frameworks/base/core/java/android/os/MessageQueue.javapublic static interface IdleHandler {/*** Called when the message queue has run out of messages and will now* wait for more.  Return true to keep your idle handler active, false* to have it removed.  This may be called if there are still messages* pending in the queue, but they are all scheduled to be dispatched* after the current time.*/boolean queueIdle();}

它是MessageQueue的内部接口类,只有queueIdle()方法,它的实现类有很多,但是执行Activity生命周期相关的在ActivityThread的内部类Idle里。

4.2 ActivityThread.Idle.queueIdle
frameworks/base/core/java/android/app/ActivityThread.javaprivate class Idler implements MessageQueue.IdleHandler {@Overridepublic final boolean queueIdle() {boolean stopProfiling = false;if (mBoundApplication != null && mProfiler.profileFd != null&& mProfiler.autoStopProfiler) {stopProfiling = true;}final ActivityClient ac = ActivityClient.getInstance();while (mNewActivities.size() > 0) {final ActivityClientRecord a = mNewActivities.remove(0);if (localLOGV) {Slog.v(TAG, "Reporting idle of " + a + " finished="+ (a.activity != null && a.activity.mFinished));}if (a.activity != null && !a.activity.mFinished) {//如果Activity存在且未处于finished状态ac.activityIdle(a.token, a.createdConfig, stopProfiling);//调用ActivityClient的activityIdle()方法a.createdConfig = null;}}if (stopProfiling) {mProfiler.stopProfiling();}return false;}}

如果Activity存在且未处于已finish状态,这里未stop的Activity就处于这种状态,调用ActivityClient的activityIdle()方法

frameworks/base/core/java/android/app/ActivityClient.java/** Reports the main thread is idle after the activity is resumed. */public void activityIdle(IBinder token, Configuration config, boolean stopProfiling) {try {getActivityClientController().activityIdle(token, config, stopProfiling);} catch (RemoteException e) {e.rethrowFromSystemServer();}}

从注释,我们也可以看出activityIdle()方法的作用:在Activity resume后报告主线程处于空闲状态。主要是通过binder调用ActivityClientController的activityIdle方法:

frameworks/base/services/core/java/com/android/server/wm/ActivityClientController.javapublic void activityIdle(IBinder token, Configuration config, boolean stopProfiling) {final long origId = Binder.clearCallingIdentity();try {synchronized (mGlobalLock) {Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "activityIdle");final ActivityRecord r = ActivityRecord.forTokenLocked(token);if (r == null) {return;}mTaskSupervisor.activityIdleInternal(r, false /* fromTimeout */,false /* processPausingActivities */, config);if (stopProfiling && r.hasProcess()) {r.app.clearProfilerIfNeeded();}}} finally {Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);Binder.restoreCallingIdentity(origId);}}

继续调用ActivityTaskSupervisor的activityIdleInternal方法

4.3 ActivityTaskSupervisor.activityIdleInternal
frameworks/base/services/core/java/com/android/server/wm/ActivityTaskSupervisor.javavoid activityIdleInternal(ActivityRecord r, boolean fromTimeout,boolean processPausingActivities, Configuration config) {if (DEBUG_ALL) Slog.v(TAG, "Activity idle: " + r);if (r != null) {if (DEBUG_IDLE) Slog.d(TAG_IDLE, "activityIdleInternal: Callers="+ Debug.getCallers(4));mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);//移除IDLE_TIMEOUT_MSG消息r.finishLaunchTickingLocked();if (fromTimeout) {reportActivityLaunched(fromTimeout, r, INVALID_DELAY, -1 /* launchState */);}// This is a hack to semi-deal with a race condition// in the client where it can be constructed with a// newer configuration from when we asked it to launch.// We'll update with whatever configuration it now says// it used to launch.if (config != null) {r.setLastReportedGlobalConfiguration(config);}// We are now idle.  If someone is waiting for a thumbnail from// us, we can now deliver.r.idle = true;// Check if able to finish booting when device is booting and all resumed activities// are idle.if ((mService.isBooting() && mRootWindowContainer.allResumedActivitiesIdle())|| fromTimeout) {checkFinishBootingLocked();}// When activity is idle, we consider the relaunch must be successful, so let's clear// the flag.r.mRelaunchReason = RELAUNCH_REASON_NONE;}if (mRootWindowContainer.allResumedActivitiesIdle()) {if (r != null) {mService.scheduleAppGcsLocked();mRecentTasks.onActivityIdle(r);}if (mLaunchingActivityWakeLock.isHeld()) {mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != SYSTEM_UID) {throw new IllegalStateException("Calling must be system uid");}mLaunchingActivityWakeLock.release();}mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);}// Atomically retrieve all of the other things to do.processStoppingAndFinishingActivities(r, processPausingActivities, "idle");//执行Activity的stop操作if (DEBUG_IDLE) {Slogf.i(TAG, "activityIdleInternal(): r=%s, mStartingUsers=%s", r, mStartingUsers);}if (!mStartingUsers.isEmpty()) {final ArrayList<UserState> startingUsers = new ArrayList<>(mStartingUsers);mStartingUsers.clear();// Complete user switch.for (int i = 0; i < startingUsers.size(); i++) {UserState userState = startingUsers.get(i);Slogf.i(TAG, "finishing switch of user %d", userState.mHandle.getIdentifier());mService.mAmInternal.finishUserSwitch(userState);}}mService.mH.post(() -> mService.mAmInternal.trimApplications());}

首先是移除IDLE_TIMEOUT_MSG消息,然后调用processStoppingAndFinishingActivities执行Activity的stop和finsih操作。先来看下这个消息是做什么的。

4.3.1 IDLE_TIMEOUT_MSG
frameworks/base/services/core/java/com/android/server/wm/ActivityTaskSupervisor.javaprivate boolean handleMessageInner(Message msg) {switch (msg.what) {......case IDLE_TIMEOUT_MSG: {if (DEBUG_IDLE) Slog.d(TAG_IDLE,"handleMessage: IDLE_TIMEOUT_MSG: r=" + msg.obj);// We don't at this point know if the activity is fullscreen, so we need to be// conservative and assume it isn't.activityIdleFromMessage((ActivityRecord) msg.obj, true /* fromTimeout */);} break;private void activityIdleFromMessage(ActivityRecord idleActivity, boolean fromTimeout) {activityIdleInternal(idleActivity, fromTimeout,fromTimeout /* processPausingActivities */, null /* config */);}void activityIdleInternal(ActivityRecord r, boolean fromTimeout,boolean processPausingActivities, Configuration config) {if (DEBUG_ALL) Slog.v(TAG, "Activity idle: " + r);......// Atomically retrieve all of the other things to do.processStoppingAndFinishingActivities(r, processPausingActivities, "idle");if (DEBUG_IDLE) {Slogf.i(TAG, "activityIdleInternal(): r=%s, mStartingUsers=%s", r, mStartingUsers);}......}

调用activityIdleFromMessage->activityIdleFromMessage方法来处理IDLE_TIMEOUT_MSG消息,从activityIdleInternal方法里可以看到,这里会调用processStoppingAndFinishingActivities执行Activity的stop和finish操作。继续看这个消息的发送时机:

frameworks/base/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
private static final int IDLE_TIMEOUT = 10 * 1000 * Build.HW_TIMEOUT_MULTIPLIER;void scheduleIdleTimeout(ActivityRecord next) {if (DEBUG_IDLE) Slog.d(TAG_IDLE, "scheduleIdleTimeout: Callers=" + Debug.getCallers(4));Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG, next);mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT);}frameworks/base/services/core/java/com/android/server/wm/ActivityRecord.javavoid completeResumeLocked() {final boolean wasVisible = mVisibleRequested;setVisibility(true);......// Schedule an idle timeout in case the app doesn't do it for us.mTaskSupervisor.scheduleIdleTimeout(this);......}

在scheduleIdleTimeout方法里定义10s的延迟消息,可以看出这个消息是在completeResumeLocked方法里发送的,即上一个Activity完成resume操作之后。

正常情况下,上一个Activity resume之后,主线程空闲下来之后就会调用stop/destory方法,但是如果主线程一直不空闲,就无法继续调用stop/destory方法。

IDLE_TIMEOUT_MSG就是系统提供的一个兜底机制,如果在上一个Activity完成resume操作之后10s主线程还没有空闲,那么系统会主动去stop/destory上一个Activity。

继续看processStoppingAndFinishingActivities操作

4.3.2 processStoppingAndFinishingActivities
frameworks/base/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java/*** Processes the activities to be stopped or destroyed. This should be called when the resumed* activities are idle or drawn.*/void processStoppingAndFinishingActivities(ActivityRecord launchedActivity,boolean processPausingActivities, String reason) {// Stop any activities that are scheduled to do so but have been waiting for the transition// animation to finish.boolean displaySwapping = false;ArrayList<ActivityRecord> readyToStopActivities = null;for (int i = 0; i < mStoppingActivities.size(); i++) {//遍历需要stop的Activityfinal ActivityRecord s = mStoppingActivities.get(i);// Activity in a force hidden task should not be counted as animating, i.e., we want to// send onStop before any configuration change when removing pip transition is ongoing.final boolean animating = s.isInTransition()&& s.getTask() != null && !s.getTask().isForceHidden();//正在进行过渡动画displaySwapping |= s.isDisplaySleepingAndSwapping();//处于正在切换状态ProtoLog.v(WM_DEBUG_STATES, "Stopping %s: nowVisible=%b animating=%b "+ "finishing=%s", s, s.nowVisible, animating, s.finishing);if ((!animating && !displaySwapping) || mService.mShuttingDown) {if (!processPausingActivities && s.isState(PAUSING)) {//不处理stop操作的情况// Defer processing pausing activities in this iteration and reschedule// a delayed idle to reprocess it againremoveIdleTimeoutForActivity(launchedActivity);//移除idle timeout消息scheduleIdleTimeout(launchedActivity);//重新计时continue;//暂时不处理这些活动}ProtoLog.v(WM_DEBUG_STATES, "Ready to stop: %s", s);if (readyToStopActivities == null) {readyToStopActivities = new ArrayList<>();}readyToStopActivities.add(s);//对于准备stop的活动,添加到readyToStopActivities列表中mStoppingActivities.remove(i);//从mStoppingActivities列表中移除该活动,表示它已经准备好被stopi--;}}// Stopping activities are deferred processing if the display is swapping. Check again// later to ensure the stopping activities can be stopped after display swapped.if (displaySwapping) {//如果有活动正在切换,延迟处理mHandler.postDelayed(() -> {synchronized (mService.mGlobalLock) {scheduleProcessStoppingAndFinishingActivitiesIfNeeded();//处理stop和finish操作}}, SCHEDULE_FINISHING_STOPPING_ACTIVITY_MS);//0.2s}final int numReadyStops = readyToStopActivities == null ? 0 : readyToStopActivities.size();//准备stop的Activity个数for (int i = 0; i < numReadyStops; i++) {//遍历即将stop的Activityfinal ActivityRecord r = readyToStopActivities.get(i);if (r.isInHistory()) {if (r.finishing) {//如果Activity正在finish// TODO(b/137329632): Wait for idle of the right activity, not just any.r.destroyIfPossible(reason);//destory销毁Activity} else {r.stopIfPossible();//否则,stop停止 Activity}}}final int numFinishingActivities = mFinishingActivities.size();//正在finish的Activity个数if (numFinishingActivities == 0) {return;}// Finish any activities that are scheduled to do so but have been waiting for the next one// to start.final ArrayList<ActivityRecord> finishingActivities = new ArrayList<>(mFinishingActivities);mFinishingActivities.clear();for (int i = 0; i < numFinishingActivities; i++) {//遍历正在finish的Activityfinal ActivityRecord r = finishingActivities.get(i);if (r.isInHistory()) {r.destroyImmediately("finish-" + reason);//立刻destory}}}

遍历mStoppingActivities列表,将符合stop条件的Activity添加到readyToStopActivities列表中;如果有Activity正在切换,添加一个200ms的延迟去处理Activity的stop操作;最后,遍历readyToStopActivities列表,如果Activity正在finishing,调用destroyIfPossible销毁Activity,否则调用stopIfPossible停止Activity。

可以看出,最终执行Activity的stop/destory操作的地方再ActivityRecord的destroyIfPossible、stopIfPossible方法,后面的流程和上面的pause流程类似。


http://www.mrgr.cn/news/80027.html

相关文章:

  • 【jvm】内存溢出内存不够的原因
  • ios h5中在fixed元素中的input被focus时,键盘遮挡input (van-popup、van-feild)
  • 打电话玩手机识别-支持YOLO,COCO,VOC格式的标记,超高识别率可检测到手持打电话, 非接触式打电话,玩手机自拍等
  • std::common_type和sfinae
  • C语言:main函数
  • Ripro V5日主题 v8.3 开心授权版 wordpress主题虚拟资源下载站首选主题模板
  • Python Bokeh库:实现实时数据可视化的实战指南
  • 力扣题目 - 2931.购买物品的最大开销
  • Python爬虫之Scrapy框架基础入门
  • 安宝特分享 | AR技术助力医院总院与分院间的远程面诊
  • Redis经典面试题
  • Mac使用总结
  • Elasticsearch Java Api Client中DSL语句的查询方法汇总(二)
  • 电脑直连设备+window使用nfs挂载设备
  • Android显示系统(10)- SurfaceFlinger内部结构
  • 【常考前端面试题总结】---2025
  • ansible自动化运维(三)jinja2模板roles角色管理
  • uni-app实现小程序、H5图片轮播预览、双指缩放、双击放大、单击还原、滑动切换功能
  • 【数据结构进阶】AVL树深度剖析 + 实现(附源码)
  • 【电机控制器】FM33LF015芯片——FLASH模拟EEPROM
  • 黑皮书-计算机科学导论02
  • react-dnd 拖拽事件与输入框的文本选中冲突
  • Opencv之图像添加水印
  • HCIA-Access V2.5_2_2网络通信基础_TCP/IP协议栈报文封装
  • SAP FICO物料分类账
  • 任务4 DNS服务配置与管理