美文网首页
activity为什么finish后ondestory会延迟

activity为什么finish后ondestory会延迟

作者: 超人TIGA | 来源:发表于2022-03-18 16:26 被阅读0次

    我们先写个例子
    例子:打开activityA -> 打开activityB ->关闭activityB

    打印下各自的生命周期: image.png
    可以看到2个特殊点:
    ①在A界面启动B界面的时候,A的生命周期只会先执行到onPause,紧接着就是执行B界面的onCreate、onStart、onResume,之后才到A界面的onStop。

    ②在B界面返回A界面的时候,B的生命周期只会先执行到onPause,紧接着就是执行A界面的onRestart、onStart、onResume,之后才到B界面的onStop、onDestory。

    这么做有什么好处?为什么android官方设计成这样?

    其实很好理解,这么处理是为了优化用户的体验。
    1、从A到B,那么用户当前准备看到的是B界面,所以先把B界面初始化好,等到主线程做完了初始化B界面的工作了,再回去做A界面的onStop的工作。
    2、从B返回A,那么用户准备看到的是A界面,所以先做好A界面的重新展示的工作,之后再回去完成B界面的onStop、onDestory的工作。

    如何验证是不是真的是这样?

    那还用说,直接看源码,首先是activity的finish方法:

    // in Activity.java
    public class Activity extends ContextThemeWrapper
            implements LayoutInflater.Factory2,
            Window.Callback, KeyEvent.Callback,
            OnCreateContextMenuListener, ComponentCallbacks2,
            Window.OnWindowDismissedCallback, WindowControllerCallback,
            AutofillManager.AutofillClient {
    
        public void finish() {
            finish(DONT_FINISH_TASK_WITH_ACTIVITY);
        }
    
        private void finish(int finishTask) {
            if (mParent == null) {
                ...
                try {
                    if (resultData != null) {
                        resultData.prepareToLeaveProcess(this);
                    }
                    if (ActivityManager.getService()
                            .finishActivity(mToken, resultCode, resultData, finishTask)) {
                        mFinished = true;
                    }
                } catch (RemoteException e) {
                    // Empty
                }
                ...
            }
        }
    }
    

    finish方法内部调用了一个带参数的私有finish方法,参数DONT_FINISH_TASK_WITH_ACTIVITY从字面意思也可以看出来,就是只关闭Activity而不关闭Activity所在的任务栈。带参数的finish方法中调用了ActivityManager.getService().finishActivity(mToken, resultCode, resultData, finishTask),通过IPC向AMS发起调用关闭当前Activity。

    // in ActivityManagerService
    public class ActivityManagerService extends IActivityManager.Stub
            implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
    
        public final boolean finishActivity(IBinder token, int resultCode, Intent resultData,
                int finishTask) {
                ...
                try {
                    boolean res;
                    final boolean finishWithRootActivity =
                            finishTask == Activity.FINISH_TASK_WITH_ROOT_ACTIVITY;
                    if (finishTask == Activity.FINISH_TASK_WITH_ACTIVITY
                            || (finishWithRootActivity && r == rootR)) {
                        res = mStackSupervisor.removeTaskByIdLocked(tr.taskId, false,
                                finishWithRootActivity, "finish-activity");
                        if (!res) {
                            Slog.i(TAG, "Removing task failed to finish activity");
                        }
                    } else {
                        // 由于finishtask标志为DONT_FINISH_TASK_WITH_ACTIVITY
                        // 因此这里进入else分支
                        res = tr.getStack().requestFinishActivityLocked(token, resultCode,
                                resultData, "app-request", true);
                        if (!res) {
                            Slog.i(TAG, "Failed to finish by app-request");
                        }
                    }
                    return res;
                } finally {
                    Binder.restoreCallingIdentity(origId);
                }
                ...
        }
    }
    
    // in ActivityStack.java
    class ActivityStack<T extends StackWindowController> extends ConfigurationContainer
            implements StackWindowListener {
    
        final boolean requestFinishActivityLocked(IBinder token, int resultCode,
                Intent resultData, String reason, boolean oomAdj) {
            ...
            finishActivityLocked(r, resultCode, resultData, reason, oomAdj);
            ...
        }
    
        final boolean finishActivityLocked(ActivityRecord r, int resultCode, Intent resultData,
                String reason, boolean oomAdj) {
            //PAUSE_IMMEDIATELY定义在ActivityStackSupervisor中
            //static final boolean PAUSE_IMMEDIATELY = true;
            //即不要立即执行暂停该Activity后的流程,而是延时500ms后再进行暂停Activity后的相关工作
            //延时500ms其实也是一种保险机制,确保后续流程一定会被执行。正常的话App侧在onPause后会发起IPC来告知AMS执行后续流程
            return finishActivityLocked(r, resultCode, resultData, reason, oomAdj, !PAUSE_IMMEDIATELY);
        }
    
        final boolean finishActivityLocked(ActivityRecord r, int resultCode, Intent resultData,
                String reason, boolean oomAdj, boolean pauseImmediately) {
            if (r.finishing) {
                Slog.w(TAG, "Duplicate finish request for " + r);
                return false;
            }
    
            mWindowManager.deferSurfaceLayout();
            try {
                //设置r.finishing=true; 标记当前Activity为finishing
                r.makeFinishingLocked();
                final TaskRecord task = r.getTask();
                EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
                        r.userId, System.identityHashCode(r),
                        task.taskId, r.shortComponentName, reason);
                final ArrayList<ActivityRecord> activities = task.mActivities;
                final int index = activities.indexOf(r);
                if (index < (activities.size() - 1)) {
                    task.setFrontOfTask();
                    if ((r.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.
                        ActivityRecord next = activities.get(index+1);
                        next.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
                    }
                }
                //停止向当前Activity分发按键消息事件
                r.pauseKeyDispatchingLocked();
                //调整当前的活动的任务栈
                adjustFocusedActivityStack(r, "finishActivity");
                //记录当前Activity要发送出去的结果数据
                finishActivityResultsLocked(r, resultCode, resultData);
    
                final boolean endTask = index <= 0 && !task.isClearingToReuseTask();
                final int transit = endTask ? TRANSIT_TASK_CLOSE : TRANSIT_ACTIVITY_CLOSE;
                if (mResumedActivity == r) {//此处,当前Activity即为活动Activity,进入if分支
                    if (DEBUG_VISIBILITY || DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
                            "Prepare close transition: finishing " + r);
                    if (endTask) {
                        mService.mTaskChangeNotificationController.notifyTaskRemovalStarted(
                                task.taskId);
                    }
                    mWindowManager.prepareAppTransition(transit, false);
    
                    // Tell window manager to prepare for this one to be removed.
                    将当前Activity设置为不可见
                    r.setVisibility(false);
    
                    if (mPausingActivity == null) {//还未暂停当前Activity,因此mPausingActivity为null
                        //开始暂停当前Activity
                        startPausingLocked(false, false, null, pauseImmediately);
                    }
    
                    if (endTask) {
                        mService.getLockTaskController().clearLockedTask(task);
                    }
                } else if (!r.isState(PAUSING)) {
                    ...
                } else {
                    ...
                }
    
                return false;
            } finally {
                ...
            }
        }
    
        final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping,
                ActivityRecord resuming, boolean pauseImmediately) {
            if (mPausingActivity != null) {
                if (!shouldSleepActivities()) { //很明显,正常情况这里为false
                    completePauseLocked(false, resuming);
                }
            }
    
            ActivityRecord prev = mResumedActivity;
            ...
            mPausingActivity = prev;
            mLastPausedActivity = prev;
            mLastNoHistoryActivity = (prev.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
                    || (prev.info.flags & ActivityInfo.FLAG_NO_HISTORY) != 0 ? prev : null;
            //设置当前Activity的状态为pausing
            prev.setState(PAUSING, "startPausingLocked");
            prev.getTask().touchActiveTime();
            clearLaunchTime(prev);
            mStackSupervisor.getLaunchTimeTracker().stopFullyDrawnTraceIfNeeded(getWindowingMode());
            mService.updateCpuStats();
    
            if (prev.app != null && prev.app.thread != null) {
                try {
                    EventLogTags.writeAmPauseActivity(prev.userId, System.identityHashCode(prev),
                            prev.shortComponentName, "userLeaving=" + userLeaving);
                    mService.updateUsageStats(prev, false);
                    //发起IPC通信,通知App侧暂定当前Activity,最终会回调Activity的onPause方法
                    mService.getLifecycleManager().scheduleTransaction(prev.app.thread, prev.appToken,
                            PauseActivityItem.obtain(prev.finishing, userLeaving,
                                    prev.configChangeFlags, pauseImmediately));
                } catch (Exception e) {
                    ...
                }
            } else {
                mPausingActivity = null;
                mLastPausedActivity = null;
                mLastNoHistoryActivity = null;
            }
    
            if (mPausingActivity != null) { //前面已经将当前Activity赋值给mPausingActivity了,因此这里不为null
                ...
                if (pauseImmediately) {//前面我们传进来的参数为!PAUSE_IMMEDIATELY,因此进入else分支
                    // If the caller said they don't want to wait for the pause, then complete
                    // the pause now.
                    completePauseLocked(false, resuming);
                    return false;
                } else {
                    //向AMS主线程发送一个延时500ms的消息,
                    schedulePauseTimeout(prev);
                    return true;
                }
            } else {
                ...
            }
        }
    }
    

    整个流程方法调用链为:在AMS中发起调用finishActivity方法,进入ActivityStack中,接着依次调用了requestFinishActivityLocked -> finishActivityLocked -> finishActivityLocked -> startPausingLocked这几个方法。在第一个调用方法finishActivityLocked中,我们详细注释了pauseImmediately参数的意义。最后,在startPausingLocked方法中,我们我们看到了这么一句代码:

    mService.getLifecycleManager().scheduleTransaction(prev.app.thread, prev.appToken,
                            PauseActivityItem.obtain(prev.finishing, userLeaving,
                                    prev.configChangeFlags, pauseImmediately));
    

    其实就是AMS通过Binder与App侧进行IPC,App侧ActivityThread中的ApplicationThread即为本次IPC通信的对端。然后App侧再通过Handler进行进程内线程间通信,通知ActivityThread中的H(继承Handler)来处理消息。H中TransactionExecutor作为真正的msg执行者,统一处理消息中所携带的任务。处理方式即执行PauseActivityItem中的execute和postExecute方法:

    // in TransactionExecutor.java
    public class TransactionExecutor {
        private void executeLifecycleState(ClientTransaction transaction) {
            //这里的lifecycleItem即为前面AMS传递过来的PauseActivityItem
            final ActivityLifecycleItem lifecycleItem = transaction.getLifecycleStateRequest();
            ...
            // Execute the final transition with proper parameters.
            //调用PauseActivityItem中的execute和postExecute方法
            lifecycleItem.execute(mTransactionHandler, token, mPendingActions);
            lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions);
        }
    }
    

    再看看PauseActivityItem,AMS发起IPC要干什么:

    // in PauseActivityItem.java
    public class PauseActivityItem extends ActivityLifecycleItem {
        @Override
        public void execute(ClientTransactionHandler client, IBinder token,
                PendingTransactionActions pendingActions) {
            //调用ActivityThread的handlePauseActivity方法,最终会回调当前Activity的onPause
            client.handlePauseActivity(token, mFinished, mUserLeaving, mConfigChanges, pendingActions,
                    "PAUSE_ACTIVITY_ITEM");
        }
    
        @Override
        public void postExecute(ClientTransactionHandler client, IBinder token,
                PendingTransactionActions pendingActions) {
            if (mDontReport) {
                return;
            }
            try {
                // TODO(lifecycler): Use interface callback instead of AMS.
                // 向AMS发起IPC,告知AMS当前Activity已经暂停,可以执行后续流程了
                // IPC对端是ActivityManagerService,最终AMS中的activityPaused方法会被调用
                ActivityManager.getService().activityPaused(token);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
        }
    }
    

    PauseActivityItem一共干了两件事,首先是回调当前Activity的onPause,然后发起IPC,告诉AMS可以执行后续流程了。我们进入ActivityManagerService来看看activityPaused方法:

    // in ActivityManagerService
    public class ActivityManagerService extends IActivityManager.Stub
            implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
    
        @Override
        public final void activityPaused(IBinder token) {
            final long origId = Binder.clearCallingIdentity();
            synchronized(this) {
                ActivityStack stack = ActivityRecord.getStackLocked(token);
                if (stack != null) {
                    stack.activityPausedLocked(token, false);
                }
            }
            Binder.restoreCallingIdentity(origId);
        }
    }
    
    // in ActivityStack.java
    class ActivityStack<T extends StackWindowController> extends ConfigurationContainer
            implements StackWindowListener {
    
        final void activityPausedLocked(IBinder token, boolean timeout) {
            final ActivityRecord r = isInStackLocked(token);
            if (r != null) {
                //前面我们发送了一个延时500ms的消息来确保后续流程一定能够得以执行
                //现在正常流程没问题,因此移除延时消息
                mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
                if (mPausingActivity == r) {
                    mService.mWindowManager.deferSurfaceLayout();
                    try {
                        //开始执行当前Activity暂停后的流程
                        //参数resumeNext为true,表示需要唤起下一个Activity
                        completePauseLocked(true /* resumeNext */, null /* resumingActivity */);
                    } finally {
                        mService.mWindowManager.continueSurfaceLayout();
                    }
                    return;
                } else {
                    ...
                }
            }
            //确保全部Activity的可见性都处于正确的状态
            mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
        }
    
        private void completePauseLocked(boolean resumeNext, ActivityRecord resuming) {
            ActivityRecord prev = mPausingActivity;
    
            if (prev != null) {
                prev.setWillCloseOrEnterPip(false);
                final boolean wasStopping = prev.isState(STOPPING);
                prev.setState(PAUSED, "completePausedLocked");
                if (prev.finishing) { //早在finishActivityLocked方法中就通过r.makeFinishingLocked()将finishing置为true了
                    //finish当前Activity
                    prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE, false,
                            "completedPausedLocked");
                } else if (prev.app != null) {
                    ...
                } else {
                    ...
                }
                if (prev != null) {
                    prev.stopFreezingScreenLocked(true /*force*/);
                }
                mPausingActivity = null;
            }
    
            if (resumeNext) { //传递进来的resumeNext为true
                final ActivityStack topStack = mStackSupervisor.getFocusedStack();
                if (!topStack.shouldSleepOrShutDownActivities()) { //看字面意思也可猜到,正常情况下进入if分支
                    mStackSupervisor.resumeFocusedStackTopActivityLocked(topStack, prev, null);
                } else {
                    ...
                }
            }
            ...
            //再次确保全部Activity的可见性都处于正确的状态
            mStackSupervisor.ensureActivitiesVisibleLocked(resuming, 0, !PRESERVE_WINDOWS);
        }
    
        final ActivityRecord finishCurrentActivityLocked(ActivityRecord r, int mode, boolean oomAdj,
                String reason) {
            //获取任务栈中栈顶Activity作为接下来即将要显示的Activity
            final ActivityRecord next = mStackSupervisor.topRunningActivityLocked(
                    true /* considerKeyguardState */);
            ...
            final ActivityState prevState = r.getState();
            r.setState(FINISHING, "finishCurrentActivityLocked");
            //很明显,当前任务栈即为前台活动任务栈,因此finishingActivityInNonFocusedStack为false
            final boolean finishingActivityInNonFocusedStack
                    = r.getStack() != mStackSupervisor.getFocusedStack()
                    && prevState == PAUSED && mode == FINISH_AFTER_VISIBLE;
            if (mode == FINISH_IMMEDIATELY // mode为FINISH_AFTER_VISIBLE false
                    || (prevState == PAUSED
                        && (mode == FINISH_AFTER_PAUSE || inPinnedWindowingMode())) // inPinnedWindowingMode() 为false
                    || finishingActivityInNonFocusedStack //false
                    || prevState == STOPPING //prevState应该为PAUSED
                    || prevState == STOPPED
                    || prevState == ActivityState.INITIALIZING) {
                //看起来是要销毁当前Activity了,好开心...然而,判断结果为false,压根不会进到if分支里面来
                r.makeFinishingLocked();
                boolean activityRemoved = destroyActivityLocked(r, true, "finish-imm:" + reason);
                ...
            }
            //虽然因为条件不符合,这里还没办法直接销毁当前Activity。但是,我们先将当前Activity放到一个列表中,该列表存储着全部即将要销毁的Activity
            mStackSupervisor.mFinishingActivities.add(r);
            r.resumeKeyDispatchingLocked();
            mStackSupervisor.resumeFocusedStackTopActivityLocked();
            return r;
        }
    }
    

    经过IPC,AMS侧收到消息,调用ActivityStack的activityPausedLocked方法开始继续后续流程。我们看到,这里ActivityStack中方法调用链为:activityPausedLocked -> completePauseLocked -> finishCurrentActivityLocked。本来追踪到finishCurrentActivityLocked方法,看到destroyActivityLocked这句代码时挺开心的,以为这就是终点了。然而,经过仔细分析,条件根本不符合,整个if分支根本得不到执行。因此,finishCurrentActivityLocked方法中仅仅是将当前Activity放到一个存储着全部要销毁的Activity列表里。再次回completePauseLocked方法中,由于需要唤起下一个Activity,因此,调用了

    //注意参数。第一个参数为当前前台活动的任务栈,第二个参数为当前正在关闭的Activity
    mStackSupervisor.resumeFocusedStackTopActivityLocked(topStack, prev, null);
    

    这行代码,我们进入StackSupervisor,看看resumeFocusedStackTopActivityLocked方法都干了啥:

    // in StackSupervisor.java
    public class ActivityStackSupervisor extends ConfigurationContainer implements DisplayListener,
            RecentTasks.Callbacks {
    
        boolean resumeFocusedStackTopActivityLocked(
                ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
            ...
            if (targetStack != null && isFocusedStack(targetStack)) {
                //根据传进来的参数,很容易知道进入if分支
                return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
            }
            ...
        }
    }
    
    // in ActivityStack.java
    class ActivityStack<T extends StackWindowController> extends ConfigurationContainer
            implements StackWindowListener {
    
        boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
            ...
            try {
                // Protect against recursion.
                mStackSupervisor.inResumeTopActivity = true;
                //唤起/显示栈顶的Activity
                result = resumeTopActivityInnerLocked(prev, options);
    
                // When resuming the top activity, it may be necessary to pause the top activity (for
                // example, returning to the lock screen. We suppress the normal pause logic in
                // {@link #resumeTopActivityUncheckedLocked}, since the top activity is resumed at the
                // end. We call the {@link ActivityStackSupervisor#checkReadyForSleepLocked} again here
                // to ensure any necessary pause logic occurs. In the case where the Activity will be
                // shown regardless of the lock screen, the call to
                // {@link ActivityStackSupervisor#checkReadyForSleepLocked} is skipped.
                final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);
                if (next == null || !next.canTurnScreenOn()) {
                    checkReadyForSleep();
                }
            } finally {
                mStackSupervisor.inResumeTopActivity = false;
            }
            ...
        }
    
        private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
            ...
            //方法很长,内容也很多,限于篇幅,这里就不仔细分析了。
            //主要是调用了:
            if (next.app != null && next.app.thread != null) {
                ...
                synchronized(mWindowManager.getWindowManagerLock()) {
                    try {
                        ...
                        //发起IPC,通知App侧要打开的Activity,最终会回调下一个要打开的Activity的onResume
                        transaction.setLifecycleStateRequest(
                                ResumeActivityItem.obtain(next.app.repProcState,
                                        mService.isNextTransitionForward()));
                        mService.getLifecycleManager().scheduleTransaction(transaction);
                    } catch (Exception e) {
                        ...
                    }
                }
    
                try {
                    // 除了通知App侧下一个要打开的Activity,AMS侧也要完成其他状态设置相关的流程
                    next.completeResumeLocked();
                } catch (Exception e) {
                    // If any exception gets thrown, toss away this
                    // activity and try the next one.
                    Slog.w(TAG, "Exception thrown during resume of " + next, e);
                    requestFinishActivityLocked(next.appToken, Activity.RESULT_CANCELED, null,
                            "resume-exception", true);
                    if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
                    return true;
                }
                ...
            }
            ...
        }
    }
    

    至此,我们需要兵分两路。一路是追踪AMS向App发起的IPC,唤起下一个要显示的Activity;一路是追踪唤起下一个Activity后AMS本身要进行的状态设置相关工作。我们先跟踪IPC流程,ResumeActivityItem与前面我们分析的PauseActivityItem一样,都是先执行execute方法,再执行postExecute方法:

    // in ResumeActivityItem.java
    public class ResumeActivityItem extends ActivityLifecycleItem {
    
        @Override
        public void execute(ClientTransactionHandler client, IBinder token,
                PendingTransactionActions pendingActions) {
            //调用ActivityThread的handleResumeActivity方法,最终会回调下一个要显示的Activity的onResume
            client.handleResumeActivity(token, true /* finalStateRequest */, mIsForward,
                    "RESUME_ACTIVITY");
        }
    
        @Override
        public void postExecute(ClientTransactionHandler client, IBinder token,
                PendingTransactionActions pendingActions) {
            try {
                // TODO(lifecycler): Use interface callback instead of AMS.
                // 向AMS发起IPC,告知AMS下一个要显示的Activity已经resume,可以执行后续流程了
                // IPC对端是ActivityManagerService,最终AMS的activityResumed方法会被调用
                ActivityManager.getService().activityResumed(token);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
        }
    }
    

    ResumeActivityItem也就干了两件事,首先是回调下一个要显示的Activity的onResume,然后发起IPC,告诉AMS可以执行后续流程了。我们再次进入ActivityManagerService来看看activityResumed方法:

    // in ActivityManagerService
    public class ActivityManagerService extends IActivityManager.Stub
            implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
    
        @Override
        public final void activityResumed(IBinder token) {
            final long origId = Binder.clearCallingIdentity();
            synchronized(this) {
                ActivityRecord.activityResumedLocked(token);
                mWindowManager.notifyAppResumedFinished(token);
            }
            Binder.restoreCallingIdentity(origId);
        }
    }
    

    如果从AMS再继续跟踪下去,线索就断了。千辛万苦分析到此处,结果还是没能挖出真相?心里一万头草泥马呼啸而过。没办法,生活还是要继续,让我们收拾好心情,回溯到上一个方法,看看ActivityThread的handleResumeActivity方法都干了些啥:

    // in ActivityThread.java
    public final class ActivityThread extends ClientTransactionHandler {
    
        @Override
        public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward,
                String reason) {
            ...
            往主线程的消息队列添加了一个空闲处理器,当主线程空闲时就会回调这个处理器来执行一些优先级较低的任务
            Looper.myQueue().addIdleHandler(new Idler());
        }
    
        private class Idler implements MessageQueue.IdleHandler {
            @Override
            public final boolean queueIdle() {
                ActivityClientRecord a = mNewActivities;
                boolean stopProfiling = false;
                if (mBoundApplication != null && mProfiler.profileFd != null
                        && mProfiler.autoStopProfiler) {
                    stopProfiling = true;
                }
                if (a != null) {
                    mNewActivities = null;
                    IActivityManager am = ActivityManager.getService();
                    ActivityClientRecord prev;
                    do {
                        if (localLOGV) Slog.v(
                            TAG, "Reporting idle of " + a +
                            " finished=" +
                            (a.activity != null && a.activity.mFinished));
                        if (a.activity != null && !a.activity.mFinished) {
                            try {
                                //发起IPC,告诉AMS侧,我(App侧)空闲了,你有什么事情需要我做的,赶紧扔过来吧
                                //最终会调用ActivityManagerService的activityIdle方法
                                am.activityIdle(a.token, a.createdConfig, stopProfiling);
                                a.createdConfig = null;
                            } catch (RemoteException ex) {
                                throw ex.rethrowFromSystemServer();
                            }
                        }
                        prev = a;
                        a = a.nextIdle;
                        prev.nextIdle = null;
                    } while (a != null);
                }
                ...
            }
        }
    }
    

    关键的代码我已经注释起来了,总而言之就是App在下一个要显示的Activity调用完onResume后往自己的主线程消息队列注册一个空闲处理器,以便App主线程的消息队列中全部msg处理完了以后能去处理一些低优先级的任务。这个空闲处理器的调用是一次性的,也就是说调用一次之后就不会再被调用了。而这个所谓的低优先级任务,其实就是App侧向AMS侧发起IPC,告诉AMS,我(App)闲下来了,你有什么需要我干的任务没有。进入ActivityManagerService,看看activityIdle方法:

    //in ActivityManagerService
    public class ActivityManagerService extends IActivityManager.Stub
            implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
        @Override
        public final void activityIdle(IBinder token, Configuration config, boolean stopProfiling) {
            final long origId = Binder.clearCallingIdentity();
            synchronized (this) {
                ActivityStack stack = ActivityRecord.getStackLocked(token);
                if (stack != null) {
                    //App侧空闲了,要干点什么好呢?
                    ActivityRecord r =
                            mStackSupervisor.activityIdleInternalLocked(token, false /* fromTimeout */,
                                    false /* processPausingActivities */, config);
                    if (stopProfiling) {
                        if ((mProfileProc == r.app) && mProfilerInfo != null) {
                            clearProfilerLocked();
                        }
                    }
                }
            }
            Binder.restoreCallingIdentity(origId);
        }
    }
    
    //in StackSupervisor
    public class ActivityStackSupervisor extends ConfigurationContainer implements DisplayListener,
            RecentTasks.Callbacks {
        final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout,
                boolean processPausingActivities, Configuration config) {
            ...
            // Finish any activities that are scheduled to do so but have been
            // waiting for the next one to start.
            //还记得前面我们分析的Activity销毁流程吧,
            //在ActivityStack的finishCurrentActivityLocked方法中,眼看就要成功,却因条件不符功亏一篑的地方吗?
            //虽然条件不符,未能调用destroyActivityLocked去销毁Activity,但当时却将需要待销毁的Activity加入到一个列表中了。
            //此处的finishes就是那个待销毁的Activity列表
            for (int i = 0; i < NF; i++) {
                r = finishes.get(i);
                final ActivityStack stack = r.getStack();
                if (stack != null) {
                    activityRemoved |= stack.destroyActivityLocked(r, true, "finish-idle");
                }
            }
            ...
        }
    }
    

    分析这么久,终于看到希望的曙光了。再接再厉,进入ActivityStack,速度瞟一眼destroyActivityLocked方法吧:

    // in ActivityStack.java
    class ActivityStack<T extends StackWindowController> extends ConfigurationContainer
            implements StackWindowListener {
        final boolean destroyActivityLocked(ActivityRecord r, boolean removeFromApp, String reason) {
            ...
            final boolean hadApp = r.app != null;
            if (hadApp) {
                ...
                boolean skipDestroy = false;
                try {
                    //发起IPC,通知App侧销毁Activity!!!
                    mService.getLifecycleManager().scheduleTransaction(r.app.thread, r.appToken,
                            DestroyActivityItem.obtain(r.finishing, r.configChangeFlags));
                } catch (Exception e) {
                    ...
                }
    
                r.nowVisible = false;
    
                // If the activity is finishing, we need to wait on removing it
                // from the list to give it a chance to do its cleanup. During
                // that time it may make calls back with its token so we need to
                // be able to find it on the list and so we don't want to remove
                // it from the list yet. Otherwise, we can just immediately put
                // it in the destroyed state since we are not removing it from the
                // list.
                if (r.finishing && !skipDestroy) {
                    r.setState(DESTROYING,
                            "destroyActivityLocked. finishing and not skipping destroy");
                    //向AMS主线程发起一个延时10s的消息,保证即使正常流程失败,也能进行Activity销毁的后续流程
                    //这里也是10s,颇具误导性。
                    //在这里绕了好久时间,最终发现,这个分支流程与我们要分析的问题关系不大
                    Message msg = mHandler.obtainMessage(DESTROY_TIMEOUT_MSG, r);
                    mHandler.sendMessageDelayed(msg, DESTROY_TIMEOUT);
                } else {
                    r.setState(DESTROYED,
                            "destroyActivityLocked. not finishing or skipping destroy");
                    r.app = null;
                }
            } else {
                ...
            }
        }
    }
    

    老规矩,让我们看看AMS发起IPC,通知App侧都干了啥。进入DestroyActivityItem,看看execute方法和postExecute方法:

    public class DestroyActivityItem extends ActivityLifecycleItem {
        @Override
        public void execute(ClientTransactionHandler client, IBinder token,
                PendingTransactionActions pendingActions) {
            //调用ActivityThread的handleDestroyActivity,最终会调用Activity的onDestroy方法
            client.handleDestroyActivity(token, mFinished, mConfigChanges,
                    false /* getNonConfigInstance */, "DestroyActivityItem");
        }
    }
    

    So easy~。呃,postExecute方法哪去了?简单,我们一路跟踪DestroyActivityItem的父类,会发现postExecute默认实现为一个空方法。
    那么,整个分析算是完成了吧。
    终于完了啊,让我放松下喘口气先~~
    等等!!!onStop方法怎么没被调用??为什么回调会延时???为什么会延时10s???
    苍天啊,搞了这么久,原来问题一个都还没解决呢??哈哈,其实不是,现在我们离真相只有一步之遥了,一个一个来。
    1、首先说下onStop方法什么时候被调用的。
    DestroyActivityItem的execute和postExecute方法谁调用的啊?前面的分析还没忘吧,是在TransactionExecutor的executeLifecycleState方法中调用的:

    // in TransactionExecutor.java
    private void executeLifecycleState(ClientTransaction transaction) {
        // Cycle to the state right before the final requested state.
        //根据Activity当前的状态和最终要到达的状态,计算中间需要经过哪些步骤
        cycleToPath(r, lifecycleItem.getTargetState(), true /* excludeLastState */);
    
        // Execute the final transition with proper parameters.
        lifecycleItem.execute(mTransactionHandler, token, mPendingActions);
        lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions);
    }
    

    看到没,关键代码是cycleToPath(),只要稍微一跟踪就可以知道在Pause和Destroy之间会执行Stop了,这个流程简单没有其他分支,因此就不详写了。
    2、onStop和onDestroy回调为什么会延时
    前面我们已经分析完了调用finish后,到回调onStop和onDestroy之间的整个正常流程。这中间经历了多次App侧和AMS侧的进程间通信,以及两端各自进程内通信。正常流程中较为关键的一点是,新的要显示的Activity在resume后,App侧的主线程空闲下来才会通知AMS执行后续流程,将关闭的Activity销毁。那要是新的Activity在resume后,主线程一直在循环处理MessageQueue中堆积的msg呢?很显然,要是这样的话,通知AMS执行后续流程自然被延迟了,因此,Activity的onStop和onDestroy生命周期回调自然也就被延迟了。
    3、延时10s是为什么
    作为一个健壮的操作系统,当然要有一定的容错机制,不能说因为App侧主线程一直忙,AMS侧就不去销毁/回收已经死亡的Activity。要不然新手开发者开发的App会因为内存泄漏等问题分分钟玩死系统。那么这个容错机制是怎么设计的呢?
    前面我们说兵分两路,一路是追踪AMS向App发起的IPC,唤起下一个要显示的Activity,一路是追踪唤起下一个Activity后AMS本身要进行的状态设置相关工作。分析完了AMS侧向App侧发起IPC后的正常流程后,我们继续分析AMS本身还做了哪些工作:

    //in ActivityStack.java
    private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
        next.completeResumeLocked();
    }
    
    // in ActivityRecord.java
    final class ActivityRecord extends ConfigurationContainer implements AppWindowContainerListener {
        void completeResumeLocked() {
            ...
            // Schedule an idle timeout in case the app doesn't do it for us.
            // 设置一个超时的空闲时间,以便在App没有通知我们其有空的情形下也能执行相关流程
            mStackSupervisor.scheduleIdleTimeoutLocked(this);
            ...
        }
    }
    
    // in StackSupervisor.java
    public class ActivityStackSupervisor extends ConfigurationContainer implements DisplayListener,
            RecentTasks.Callbacks {
        void scheduleIdleTimeoutLocked(ActivityRecord next) {
            //真相就在这里,发送一个延时10s的消息,确保正常流程行不通的情况下也能销毁Activity
            Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG, next);
            mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT);
        }
    
        private final class ActivityStackSupervisorHandler extends Handler {
            void activityIdleInternal(ActivityRecord r, boolean processPausingActivities) {
                synchronized (mService) {
                    //在前面我们分析正常流程的时候,已经将该方法的执行流程分析完了,不再赘述
                    activityIdleInternalLocked(r != null ? r.appToken : null, true /* fromTimeout */,
                            processPausingActivities, null);
                }
            }
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                    case IDLE_TIMEOUT_MSG: {
                        //延时10s后,就当Activity侧已经空闲下来了,执行后续流程
                        activityIdleInternal((ActivityRecord) msg.obj,
                                true /* processPausingActivities */);
                    } break;
                    ...
                }
            }
    }
    

    好了。这下是真的分析完了。
    因为源码是在太长了,因此省略了很多分支流程和与主题无关的代码。
    说是分析回调延时的问题,其实也即是分析finish的源码调用流程。通过分析,我们知道,要想使得Activity的onStop和onDestroy尽快得到回调,我们就该在写代码的时候,及时关闭、清理、移除不必要的主线程消息,并且尽可能的保证每个消息处理时间不要太长。
    经过这一波分析,该对Framework层App和AMS的交互有了更清晰的理解了吧。

    相关文章

      网友评论

          本文标题:activity为什么finish后ondestory会延迟

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