这篇文章通过追踪AMS源码(api28),走一遍执行onStop()的流程,先来一张流程图:
两个Activity之间切换后,上一个Activity切换到OnStop状态;或者调用finish()后,到Activity回收切换到最终的OnDestroy状态,AMS的机制是,等主线程空闲时,再通知AMS执行Activity的可见性切换(Onstop()),Activity的回收(OnDestroy()),目的是由于OnStop,OnDestroy这个两个状态的切换并不影响界面的显示和点击事件分发,属于低优先级的行为,不紧跟OnPause,OnResume这个两个状态切换之后执行,可以避免主线程处理过多操作,导致Activity的切换动画卡顿。在AMS端也存在保护机制,当app进程执行完handleResumeActivity()回调到AMS的completeResumeLocked()就会开启超时10秒的任务去通知执行Activity的可见性切换(Onstop()),Activity的回收(OnDestroy()),这样做的目标是避免app进程的主线程一直不空闲,导致这操作永远执行不到。
从源码开始追踪(省略无关的代码):
本次追踪分为四部分(1、当前目标activity切换ON_RESUME状态后,将上一个activity放到等待执行切换到ON_STOP状态的队列中;2、app进程端开始;3、AMS开始;4、AMS开始执行Activity切换onStop)
目录
1、AMS通知目标activity切换到ON_RESUME状态后,将上一个可见的activity放到切换到ON_STOP状态的等待处理队列中
1.1、ActivityRecord#completeResumeLocked
1.2、ActivityStackSupervisor#reportResumedActivityLocked
1.3、ActivityStackSupervisor#ensureActivitiesVisibleLocked
1.4、ActivityStack#ensureActivitiesVisibleLocked
1.5、ActivityStack#makeInvisible
1.6、ActivityStack#addToStopping
2、app进程执行完handleResumeActivity方法之后开始
2.2、ActivityManagerService#activityIdle
3、将需要切换到ON_STOP状态的activity加入队列后,AMS将发送一个超时10秒的任务,确保app端主线繁忙时,也是执行对应切换生命周期操作
3.1、ActivityStackSupervisor#scheduleIdleTimeoutLocked(即1.5中,对应那个方法)
4.1、ActivityStackSupervisor#activityIdleInternalLocked
1、AMS通知目标activity切换到ON_RESUME状态后,将上一个可见的activity放到切换到ON_STOP状态的等待处理队列中
1.1、ActivityRecord#completeResumeLocked
void completeResumeLocked() {
...
// 执行切换到ON_RESUME状态后的操作
mStackSupervisor.reportResumedActivityLocked(this);
...
}
1.2、ActivityStackSupervisor#reportResumedActivityLocked
boolean reportResumedActivityLocked(ActivityRecord r) {
// 从等待切换到ON_STOP状态的队列中移除
mStoppingActivities.remove(r);
...
// 必须在目标activity切换到ON_RESUME状态流程完整后,才可以调整其他activity的可见状态(确定那
// 些activity需要进入ON_STOP状态)
if (allResumedActivitiesComplete()) {
ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
mWindowManager.executeAppTransition();
return true;
}
return false;
}
1.3、ActivityStackSupervisor#ensureActivitiesVisibleLocked
void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges,
boolean preserveWindows, boolean notifyClients) {
getKeyguardController().beginActivityVisibilityUpdate();
try {
// 遍历一下所有的activity的可见状态
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx)
{
final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = display.getChildAt(stackNdx);
stack.ensureActivitiesVisibleLocked(starting,configChanges,preserveWindows,
notifyClients);
}
}
} finally {
getKeyguardController().endActivityVisibilityUpdate();
}
}
1.4、ActivityStack#ensureActivitiesVisibleLocked
final void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges,
boolean preserveWindows, boolean notifyClients) {
...
// 顶层可见的activity
ActivityRecord top = topRunningActivityLocked();
// 判断当前最顶层的activity是否是完全可见(即盖住下面全部的activity,不是半透明activity)
final boolean stackShouldBeVisible = shouldBeVisible(starting);
boolean behindFullscreenActivity = !stackShouldBeVisible;
// 遍历一下所有的activity
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
final TaskRecord task = mTaskHistory.get(taskNdx);
final ArrayList<ActivityRecord> activities = task.mActivities;
for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
// 开始判断每个activity
final ActivityRecord r = activities.get(activityNdx);
// 如果已经finish的跳过不管
if (r.finishing) {
continue;
}
// 判断该activity是否可见
final boolean visibleIgnoringKeyguard = r.shouldBeVisibleIgnoringKeyguard(
behindFullscreenActivity);
r.visibleIgnoringKeyguard = visibleIgnoringKeyguard;
final boolean reallyVisible = checkKeyguardVisibility(r,
visibleIgnoringKeyguard, isTop && isTopNotPinnedStack);
// 如果该activity为可见状态
if (reallyVisible) {
// 如果该activity不存在
if (r.app == null || r.app.thread == null) {
// 需要重启该activity
if (makeVisibleAndRestartIfNeeded(starting, configChanges, isTop,
resumeNextActivity, r)) {
...
}
}
// 如果该activity已经可见了
else if (r.visible) {
// 如果需要通知app端
if (r.mClientVisibilityDeferred && notifyClients) {
// 通知一下对应的activity切换可见性
r.makeClientVisible();
}
}else{
// 通知对应的activity切换可见性
r.makeVisibleIfNeeded(starting, notifyClients);
}
}
// 如果该activity为不可见状态
else{
// 将该activity设置为不可见状态
makeInvisible(r);
}
...
}
}
}
1.5、ActivityStack#makeInvisible
private void makeInvisible(ActivityRecord r) {
// 如果已经为不可见状态
if (!r.visible) {
return;
}
...
switch (r.getState()) {
// 如果已经是停止,需要通知app端的activity切换到正确的可见状态
case STOPPING:
case STOPPED:
if (r.app != null && r.app.thread != null) {
if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,
"Scheduling invisibility: " + r);
mService.getLifecycleManager().scheduleTransaction(r.app.thread,
r.appToken,WindowVisibilityItem.obtain(false /* showWindow */));
}
r.supportsEnterPipOnTaskSwitch = false;
break;
// 如果在一下这些状态,需要加到准备切换到ON_STOP的队列中
case INITIALIZING:
case RESUMED:
case PAUSING:
case PAUSED:
addToStopping(r, true /* scheduleIdle */,canEnterPictureInPicture /*
idleDelayed */);
break;
default:
break;
}
}
1.6、ActivityStack#addToStopping
void addToStopping(ActivityRecord r, boolean scheduleIdle, boolean idleDelayed) {
if (!mStackSupervisor.mStoppingActivities.contains(r)) {
mStackSupervisor.mStoppingActivities.add(r);
}
...
// 超时10执行状态切换
mStackSupervisor.scheduleIdleTimeoutLocked(r);
}
2、app进程执行完handleResumeActivity方法之后开始
@Override
public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward,String reason) {
...
// 执行完,往主线程插入一个任务,等主线程空闲时执行
Looper.myQueue().addIdleHandler(new Idler());
}
2.1、Idler#queueIdle
private class Idler implements MessageQueue.IdleHandler {
@Override
public final boolean queueIdle() {
// 当前活跃的activity
ActivityClientRecord a = mNewActivities;
...
// 通知AMS开始执行操作
am.activityIdle(a.token, a.createdConfig, stopProfiling);
...
}
}
2.2、ActivityManagerService#activityIdle
public final void activityIdle(IBinder token, Configuration config, boolean stopProfiling){
synchronized (this) {
mStackSupervisor.activityIdleInternalLocked(token, false /* fromTimeout */,
false /* processPausingActivities */, config);
}
}
3、将需要切换到ON_STOP状态的activity加入队列后,AMS将发送一个超时10秒的任务,确保app端主线繁忙时,也是执行对应切换生命周期操作
3.1、ActivityStackSupervisor#scheduleIdleTimeoutLocked(即1.5中,对应那个方法)
void scheduleIdleTimeoutLocked(ActivityRecord next) {
Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG, next);
mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT/*10*/);
}
4、AMS开始执行目标Activity切换onStop状态
4.1、ActivityStackSupervisor#activityIdleInternalLocked
final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout,
boolean processPausingActivities, Configuration config) {
...
final ArrayList<ActivityRecord> stops = processStoppingActivitiesLocked(r,
true /* remove */, processPausingActivities);
NS = stops != null ? stops.size() : 0;
if ((NF = mFinishingActivities.size()) > 0) {
finishes = new ArrayList<>(mFinishingActivities);
mFinishingActivities.clear();
}
if (mStartingUsers.size() > 0) {
startingUsers = new ArrayList<>(mStartingUsers);
mStartingUsers.clear();
}
// 将在队列中的activity执行切换到ON_STOP生命周期
for (int i = 0; i < NS; i++) {
r = stops.get(i);
final ActivityStack stack = r.getStack();
if (stack != null) {
// 如果该activity已经finish了,需要将它排进finish的队列中
if (r.finishing) {
stack.finishCurrentActivityLocked(r, ActivityStack.FINISH_IMMEDIATELY,
false,"activityIdleInternalLocked");
} else {
stack.stopActivityLocked(r);
}
}
}
// 将在队列中的activity执行切换到ON_DESTROY生命周期
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");
}
}
}
总结:通过本次的代码追踪,就是知道为啥OnStop和OnDestory不是跟在OnPause之后立马执行,而是延迟执行且最迟会延迟到10秒执行。如果内存不足,这个两个方法可能存在不执行的情况。故我们在使用activity生命周期回调做一些全局方法的调用,就需要处理调用时序问题和可能存在泄漏的问题。