android 退出Activity源码分析
我们首先知道退出应用是从最后的一个activity的finish方法开始的。
/**
* Finishes the current activity and specifies whether to remove the task associated with this
* activity.
*/
private 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);
try {
if (resultData != null) {
resultData.prepareToLeaveProcess(this);
}
if (ActivityManagerNative.getDefault()
.finishActivity(mToken, resultCode, resultData, finishTask)) {
mFinished = true;
}
} catch (RemoteException e) {
// Empty
}
} else {
mParent.finishFromChild(this);
}
}
很显然,最主要的方法是ActivityManagerNative.getDefault().finishActivity(mToken, resultCode, resultData, finishTask),那么我们就来看AMS的finishActivity做了什么?:
else {
res = tr.stack.requestFinishActivityLocked(token, resultCode,
resultData, "app-request", true);
if (!res) {
Slog.i(TAG, "Failed to finish by app-request");
}
}
代码比较长,最主要的就是上面的这一段,紧接着我们可以进入到finishActivityLocked方法:
/**
* @return Returns true if this activity has been removed from the history
* list, or false if it is still in the list and will be removed later.
*/
final boolean finishActivityLocked(ActivityRecord r, int resultCode, Intent resultData,
String reason, boolean oomAdj) {
...
if (mResumedActivity == r) {
if (DEBUG_VISIBILITY || DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
"Prepare close transition: finishing " + r);
mWindowManager.prepareAppTransition(transit, false);
// Tell window manager to prepare for this one to be removed.
mWindowManager.setAppVisibility(r.appToken, false);
if (mPausingActivity == null) {
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish needs to pause: " + r);
if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
"finish() => pause with userLeaving=false");
startPausingLocked(false, false, null, false);
}
if (endTask) {
mStackSupervisor.removeLockedTaskLocked(task);
}
} else if (r.state != ActivityState.PAUSING) {
// If the activity is PAUSING, we will complete the finish once
// it is done pausing; else we can just directly finish it here.
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish not pausing: " + r);
if (r.visible) {
mWindowManager.prepareAppTransition(transit, false);
mWindowManager.setAppVisibility(r.appToken, false);
mWindowManager.executeAppTransition();
if (!mStackSupervisor.mWaitingVisibleActivities.contains(r)) {
mStackSupervisor.mWaitingVisibleActivities.add(r);
}
}
return finishCurrentActivityLocked(r, (r.visible || r.nowVisible) ?
FINISH_AFTER_VISIBLE : FINISH_AFTER_PAUSE, oomAdj) == null;
} else {
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish waiting for pause of: " + r);
}
return false;
}
主要是两个方法,startPausingLocked和finishCurrentActivityLocked,我们先看前者:
final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping,
ActivityRecord resuming, boolean dontWait) {
...
if (prev.app != null && prev.app.thread != null) {
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending pause: " + prev);
try {
EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
prev.userId, System.identityHashCode(prev),
prev.shortComponentName);
mService.updateUsageStats(prev, false);
prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
userLeaving, prev.configChangeFlags, dontWait);
} catch (Exception e) {
// Ignore exception, if process died other code will cleanup.
Slog.w(TAG, "Exception thrown during pause", e);
mPausingActivity = null;
mLastPausedActivity = null;
mLastNoHistoryActivity = null;
}
} else {
mPausingActivity = null;
mLastPausedActivity = null;
mLastNoHistoryActivity = null;
}
...
}
我们可以看到,由于是AMS发起的方法,那么可能是跨进程的调用,那么就直接调用ActivityRecord.app.thread去调用applicationThread的schedulePauseActivity方法(这个ApplicationThread是ActivityThread的内部类,也是binder的东西),然后我们知道在schedulePauseActivity方法就会去执行activity的pause操作,并且回调onPause方法,一路追溯,来到handlePauseActivity方法:
private void handlePauseActivity(IBinder token, boolean finished,
boolean userLeaving, int configChanges, boolean dontReport, int seq) {
ActivityClientRecord r = mActivities.get(token);
if (DEBUG_ORDER) Slog.d(TAG, "handlePauseActivity " + r + ", seq: " + seq);
if (!checkAndUpdateLifecycleSeq(seq, r, "pauseActivity")) {
return;
}
if (r != null) {
//Slog.v(TAG, "userLeaving=" + userLeaving + " handling pause of " + r);
if (userLeaving) {
performUserLeavingActivity(r);
}
r.activity.mConfigChangeFlags |= configChanges;
performPauseActivity(token, finished, r.isPreHoneycomb(), "handlePauseActivity");
// Make sure any pending writes are now committed.
if (r.isPreHoneycomb()) {
QueuedWork.waitToFinish();
}
// Tell the activity manager we have paused.
if (!dontReport) {
try {
ActivityManagerNative.getDefault().activityPaused(token);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
mSomeActivitiesChanged = true;
}
}
其中performPauseActivity方法就是去pause并且回调onPause的,另外一个就是ActivityManagerNative.getDefault().activityPaused(token)去调AMS服务的activityPaused方法,一路看下去,最后终归会去调用finishCurrentActivityLocked方法,就是最最前面我们需要分析的第二个方法了:
final ActivityRecord finishCurrentActivityLocked(ActivityRecord r, int mode, boolean oomAdj) {
...
if (mode == FINISH_IMMEDIATELY
|| (prevState == ActivityState.PAUSED
&& (mode == FINISH_AFTER_PAUSE || mStackId == PINNED_STACK_ID))
|| finishingActivityInNonFocusedStack
|| prevState == ActivityState.STOPPED
|| prevState == ActivityState.INITIALIZING) {
r.makeFinishingLocked();
boolean activityRemoved = destroyActivityLocked(r, true, "finish-imm");
if (finishingActivityInNonFocusedStack) {
// Finishing activity that was in paused state and it was in not currently focused
// stack, need to make something visible in its place.
mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
}
if (activityRemoved) {
mStackSupervisor.resumeFocusedStackTopActivityLocked();
}
if (DEBUG_CONTAINERS) Slog.d(TAG_CONTAINERS,
"destroyActivityLocked: finishCurrentActivityLocked r=" + r +
" destroy returned removed=" + activityRemoved);
return activityRemoved ? null : r;
}
...
}
重要的就是这个destroyActivityLocked方法,继续看:
final boolean destroyActivityLocked(ActivityRecord r, boolean removeFromApp, String reason) {
...
try {
if (DEBUG_SWITCH) Slog.i(TAG_SWITCH, "Destroying: " + r);
r.app.thread.scheduleDestroyActivity(r.appToken, r.finishing,
r.configChangeFlags);
} catch (Exception e) {
// We can just ignore exceptions here... if the process
// has crashed, our death notification will clean things
// up.
//Slog.w(TAG, "Exception thrown during finish", e);
if (r.finishing) {
removeActivityFromHistoryLocked(
r, topTask, reason + " exceptionInScheduleDestroy");
removedFromHistory = true;
skipDestroy = true;
}
}
...
}
scheduleDestroyActivity方法,好了吧,一目了然了吧。但是看到这里也许有的人会问,怎么没有stop方法,这里我们在深入一下,你可以顺这再去看,在performDestoryActivity方法中,我们可以找到这样一段:
if (!r.stopped) {
try {
r.activity.performStop(r.mPreserveWindow);
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {
if (!mInstrumentation.onException(r.activity, e)) {
throw new RuntimeException(
"Unable to stop activity "
+ safeToComponentShortString(r.intent)
+ ": " + e.toString(), e);
}
}
r.stopped = true;
EventLog.writeEvent(LOG_AM_ON_STOP_CALLED, UserHandle.myUserId(),
r.activity.getComponentName().getClassName(), "destroy");
}