activity为什么finish后ondestory会延迟

2022-03-18  本文已影响0人  超人TIGA

我们先写个例子
例子:打开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的交互有了更清晰的理解了吧。

上一篇下一篇

猜你喜欢

热点阅读