上一篇我們分析了Activity的啟動流程忌愚,由于代碼量很大,還是沒有分析的很詳細(xì)却邓,但是基本流程都出來了硕糊,更詳細(xì)的東西還是要去看源碼,源碼在我文章的最后有給出腊徙,里面有我添加的詳細(xì)的注釋简十。這一章來分析Activity的finish過程,這個問題在兩年前我去面試金山的時候曾經(jīng)被問到過撬腾,那時候?qū)υ创a基本沒什么了解螟蝙,所以當(dāng)時根本是不了解的,今天我們就來分析一下finish的過程到底做了哪些處理民傻,最后對Activity的整個啟動過程以及finish過程繪制流程圖胰默,以方便我們記憶。
finish代碼分析
首先先貼一張時序圖:
Activity的finish方法就是調(diào)用的父類的finish方法:
Step1.Activity.finish
public void finish() {
finish(DONT_FINISH_TASK_WITH_ACTIVITY);
}
這里調(diào)用finish方法漓踢,傳入?yún)?shù)DONT_FINISH_TASK_WITH_ACTIVITY牵署,這個參數(shù)是在finish掉Activity的時候不finish掉Task。
Step2.Activity.finish
private void finish(int finishTask) {
...
if (ActivityManagerNative.getDefault()
.finishActivity(mToken, resultCode, resultData, finishTask)) {
mFinished = true;
}
...
}
ActivityManagerNative.getDefault()方法其實(shí)我們在前面文章提到過喧半,得到的是AMP(ActivityManagerProxy)奴迅。
Step3.AMP.finishActivity
public boolean finishActivity(IBinder token, int resultCode, Intent resultData, int finishTask)
throws RemoteException {
...
mRemote.transact(FINISH_ACTIVITY_TRANSACTION, data, reply, 0);
...
}
通過Binder調(diào)用AMS的finishActivity方法。
Step4.AMS.finishActivity
public final boolean finishActivity(IBinder token, int resultCode, Intent resultData,
int finishTask) {
...
synchronized (this) {
// 根據(jù)token(IBinder)獲取Activity的對象封裝ActivityRecord
ActivityRecord r = ActivityRecord.isInStackLocked(token);
if (r == null) {
return true;
}
// Keep track of the root activity of the task before we finish it
TaskRecord tr = r.task;
// 從棧底部獲取第一沒有被finish的Activity對象封裝
ActivityRecord rootR = tr.getRootActivity();
...
if (mController != null) {
// Find the first activity that is not finishing.
// 獲取第一個沒有被回收的Activity
ActivityRecord next = r.task.stack.topRunningActivityLocked(token, 0);
if (next != null) {
...
}
}
final long origId = Binder.clearCallingIdentity();
try {
// 傳入的finishTask是DONT_FINISH_TASK_WITH_ACTIVITY挺据,所以下面參數(shù)是false
final boolean finishWithRootActivity =
finishTask == Activity.FINISH_TASK_WITH_ROOT_ACTIVITY;
// 這里if中條件為false所以走else語句
if (finishTask == Activity.FINISH_TASK_WITH_ACTIVITY
|| (finishWithRootActivity && r == rootR)) {
res = removeTaskByIdLocked(tr.taskId, false, finishWithRootActivity);
...
} else {
res = tr.stack.requestFinishActivityLocked(token, resultCode,
resultData, "app-request", true);
...
}
return res;
} finally {
...
}
}
}
上面try語句中會走else語句中的方法也就是ActivityStack.requestFinishActivityLocked
Step5.ActivityStack.requestFinishActivityLocked
final boolean requestFinishActivityLocked(IBinder token, int resultCode,
Intent resultData, String reason, boolean oomAdj) {
ActivityRecord r = isInStackLocked(token);
...
finishActivityLocked(r, resultCode, resultData, reason, oomAdj);
return true;
}
調(diào)用finishActivityLocked方法
Step6.ActivityStack.finishActivityLocked
final boolean finishActivityLocked(ActivityRecord r, int resultCode, Intent resultData,
String reason, boolean oomAdj) {
if (r.finishing) {// 如果要清理的的正在finish取具,則不需要再清理
Slog.w(TAG, "Duplicate finish request for " + r);
return false;
}
// 標(biāo)記開始finish
r.makeFinishingLocked();
...
// 停止鍵盤分發(fā)事件
r.pauseKeyDispatchingLocked();
adjustFocusedActivityLocked(r, "finishActivity");
finishActivityResultsLocked(r, resultCode, resultData);
// 如果任務(wù)中沒有了Activity要結(jié)束任務(wù)
final boolean endTask = index <= 0;
final int transit = endTask ? TRANSIT_TASK_CLOSE : TRANSIT_ACTIVITY_CLOSE;
if (mResumedActivity == r) {// 如果當(dāng)前顯示的Activity就是要結(jié)束的Activity
...
if (mPausingActivity == null) {
// 開始暫停Activity
startPausingLocked(false, false, null, false);
}
if (endTask) {// 如果任務(wù)中沒有了Activity,則移除任務(wù)
mStackSupervisor.removeLockedTaskLocked(task);
}
} else if (r.state != ActivityState.PAUSING) {// 如果要移除的Activity不是Pausing狀態(tài)并且不是正在顯示的Activity
...
return finishCurrentActivityLocked(r, (r.visible || r.nowVisible) ?
FINISH_AFTER_VISIBLE : FINISH_AFTER_PAUSE, oomAdj) == null;
} else {
...
}
return false;
}
這里首先調(diào)用ActivityRecord.makeFinishingLocked標(biāo)記開始結(jié)束Activity扁耐,然后調(diào)用ActivityRecord.pauseKeyDispatchingLocked方法停止鍵盤事件分發(fā)暇检。然后調(diào)用adjustFocusedActivityLocked方法,調(diào)整Activity的焦點(diǎn)狀體做葵。
Step7.ActivityStack.adjustFocusedActivityLocked
private void adjustFocusedActivityLocked(ActivityRecord r, String reason) {
// 如果當(dāng)前棧沒有焦點(diǎn)占哟,或者當(dāng)前Activity也不是當(dāng)前有焦點(diǎn)的Activity,返回
if (!mStackSupervisor.isFocusedStack(this) || mService.mFocusedActivity != r) {
return;
}
// 獲取棧頂正在運(yùn)行的Activity
final ActivityRecord next = topRunningActivityLocked();
final String myReason = reason + " adjustFocus";
if (next != r) {// 如果棧頂正在運(yùn)行的不是當(dāng)前要結(jié)束的Activity
if (next != null && StackId.keepFocusInStackIfPossible(mStackId) && isFocusable()) {
mService.setFocusedActivityLocked(next, myReason);
return;
} else {
final TaskRecord task = r.task;
if (r.frontOfTask && task == topTask() && task.isOverHomeStack()) {
final int taskToReturnTo = task.getTaskToReturnTo();
if (!mFullscreen
&& adjustFocusToNextFocusableStackLocked(taskToReturnTo, myReason)) {
return;
}
if (mStackSupervisor.moveHomeStackTaskToTop(taskToReturnTo, myReason)) {
return;
}
}
}
}
mService.setFocusedActivityLocked(mStackSupervisor.topRunningActivityLocked(), myReason);
}
當(dāng)前Activity要finish掉酿矢,就找找到下一個應(yīng)該獲取焦點(diǎn)的Activity榨乎,在該Activity被finish掉之后顯示出來。
Step8.ActivityStack.finishActivityResultsLocked
final void finishActivityResultsLocked(ActivityRecord r, int resultCode, Intent resultData) {
// send the result
ActivityRecord resultTo = r.resultTo;
if (resultTo != null) {
...
resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode,
resultData);
r.resultTo = null;
} else if (DEBUG_RESULTS) Slog.v(TAG_RESULTS, "No result destination from " + r);
...
}
如果要接收Result的Activity描述對象ActivityRecord還存在瘫筐,就將result相關(guān)信息封裝成ActivityResult對象放到ActivityResult列表中保存起來蜜暑。然后置空該Activity對應(yīng)的ActivityRecord對象中的信息。
Step9.ActivityStack.startPausingLocked
final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping,
ActivityRecord resuming, boolean dontWait) {
if (mPausingActivity != null) {
Slog.wtf(TAG, "Going to pause when pause is already pending for " + mPausingActivity
+ " state=" + mPausingActivity.state);
if (!mService.isSleepingLocked()) {// 如果沒有在睡眠策肝,則完成Pause狀態(tài)
completePauseLocked(false, resuming);
}
}
// prev指向源Activity
ActivityRecord prev = mResumedActivity;
if (prev == null) {
if (resuming == null) {
Slog.wtf(TAG, "Trying to pause when nothing is resumed");
mStackSupervisor.resumeFocusedStackTopActivityLocked();
}
return false;
}
if (mActivityContainer.mParentActivity == null) {
// Top level stack, not a child. Look for child stacks.
// 暫停所有子棧的Activity
mStackSupervisor.pauseChildStacks(prev, userLeaving, uiSleeping, resuming, dontWait);
}
...
// 改變狀態(tài)
prev.state = ActivityState.PAUSING;
...
// 獲取正在啟動的Activity組件
final ActivityRecord next = mStackSupervisor.topRunningActivityLocked();
...
if (prev.app != null && prev.app.thread != null) {
...
// 通知源Activity組件肛捍,暫停源Activity以便有機(jī)會執(zhí)行一些數(shù)據(jù)保存操作隐绵,
// 這里如果目標(biāo)sdk<11會調(diào)用onSaveInstanceState,然后調(diào)用onPause
prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
userLeaving, prev.configChangeFlags, dontWait);
...
} else {
...
}
...
}
這里主要是在finish之前pause該Activity拙毫,如果狀態(tài)正常會調(diào)用schedulePauseActivity方法依许,最終調(diào)用Activity的onPause方法,這個過程我們在前面講過幾次了缀蹄,這里就不再分析峭跳,比較簡單。我們接著看核心的代碼缺前。
Step10.ActivityStack.finishCurrentActivityLocked
final ActivityRecord finishCurrentActivityLocked(ActivityRecord r, int mode, boolean oomAdj) {
// 如果當(dāng)前要finish的Activity正在顯示蛀醉,而復(fù)用的Activity還沒有顯示,那么延遲finish衅码,
// 直到復(fù)用Activity顯示
// 獲取頂部正在運(yùn)行的Activity
final ActivityRecord next = mStackSupervisor.topRunningActivityLocked();
// 如果是顯示后在finish拯刁,并且要結(jié)束的正在顯示或者將要顯示,并且頂部運(yùn)行的存在而且沒有顯示
if (mode == FINISH_AFTER_VISIBLE && (r.visible || r.nowVisible)
&& next != null && !next.nowVisible) {
// 如果當(dāng)前要結(jié)束的Activity不在正在停止列表中則添加到停止列表中
if (!mStackSupervisor.mStoppingActivities.contains(r)) {
addToStopping(r, false /* immediate */);
}
...
return r;
}
// make sure the record is cleaned out of other places.
// 從各個列表中清理這個將要被finish的Activity
...
final ActivityState prevState = r.state;// 存儲清理之前的狀態(tài)
r.state = ActivityState.FINISHING;// 設(shè)置為正在finish狀態(tài)
// 判斷當(dāng)前正在清理的Activity是否在當(dāng)前獲取焦點(diǎn)的棧中
final boolean finishingActivityInNonFocusedStack
= r.task.stack != mStackSupervisor.getFocusedStack()
&& prevState == ActivityState.PAUSED && mode == FINISH_AFTER_VISIBLE;
if (mode == FINISH_IMMEDIATELY
|| (prevState == ActivityState.PAUSED
&& (mode == FINISH_AFTER_PAUSE || mStackId == PINNED_STACK_ID))
|| finishingActivityInNonFocusedStack
|| prevState == ActivityState.STOPPED
|| prevState == ActivityState.INITIALIZING) {
...
// 銷毀Activity
boolean activityRemoved = destroyActivityLocked(r, true, "finish-imm");
...
return activityRemoved ? null : r;
}
...
return r;
}
這里是開始銷毀Activity逝段,首先要保存狀態(tài)垛玻,然后標(biāo)記開始finish,然后調(diào)用destroyActivityLocked方法開始銷毀奶躯。
Step11.ActivityStack.destroyActivityLocked
final boolean destroyActivityLocked(ActivityRecord r, boolean removeFromApp, String reason) {
...
// 清理Activity
cleanUpActivityLocked(r, false, false);
final boolean hadApp = r.app != null;
if (hadApp) {
...
boolean skipDestroy = false;
try {
r.app.thread.scheduleDestroyActivity(r.appToken, r.finishing,
r.configChangeFlags);
} catch (Exception e) {
...
}
...
return removedFromHistory;
}
這里主要有兩部操作夭谤,第一步是cleanUpActivityLocked,第二步是scheduleDestroyActivity巫糙。我們先看第一步朗儒。
Step12.ActivityStack.cleanUpActivityLocked
final void cleanUpActivityLocked(ActivityRecord r, boolean cleanServices,
boolean setState) {
if (mResumedActivity == r) {
mResumedActivity = null;
}
if (mPausingActivity == r) {
mPausingActivity = null;
}
mService.resetFocusedActivityIfNeededLocked(r);
...
// Make sure this record is no longer in the pending finishes list.
// This could happen, for example, if we are trimming activities
// down to the max limit while they are still waiting to finish.
mStackSupervisor.mFinishingActivities.remove(r);
mStackSupervisor.mWaitingVisibleActivities.remove(r);
...
if (cleanServices) {// 是否清理服務(wù)
cleanUpActivityServicesLocked(r);
}
...
}
這里主要是將指向該銷毀的Activity的引用都置空,進(jìn)行釋放参淹,然后將該Activity描述對象從列表中移除該對象醉锄,最后是判斷是否清理服務(wù),其實(shí)主要是綁定該Activity的服務(wù)浙值,如果有綁定則解除綁定恳不。
Step13.ActivityManagerService.resetFocusedActivityIfNeededLocked
// 重新設(shè)置獲取焦點(diǎn)的Activity,如果被清理的不是獲取焦點(diǎn)的开呐,那么不處理烟勋,否則將焦點(diǎn)移動到另外一個Activity
final void resetFocusedActivityIfNeededLocked(ActivityRecord goingAway) {
...
// Try to move focus to another activity if possible.
// 如果允許,將焦點(diǎn)移動到另外一個Activity
if (setFocusedActivityLocked(
focusedStack.topRunningActivityLocked(), "resetFocusedActivityIfNeeded")) {
return;
}
...
}
這里調(diào)用setFocusedActivityLocked方法判斷該Activity是不是允許允許將焦點(diǎn)移除筐付。
Step14.ActivityManagerService.setFocusedActivityLocked
boolean setFocusedActivityLocked(ActivityRecord r, String reason) {
if (r == null || mFocusedActivity == r) {// 如果傳入的焦點(diǎn)Activity不存在或者就是顯示在有焦點(diǎn)的Activity則不需要處理了
return false;
}
if (!r.isFocusable()) {// 如果沒有獲取焦點(diǎn)卵惦,返回
return false;
}
...
// 獲取之前有焦點(diǎn)的Activity
final ActivityRecord last = mFocusedActivity;
mFocusedActivity = r;// 設(shè)置傳入的Activity為當(dāng)前焦點(diǎn)Activity
if (r.task.isApplicationTask()) {// 當(dāng)前焦點(diǎn)Activity所在任務(wù)是應(yīng)用任務(wù)(不是桌面和最近應(yīng)用界面)
if (mCurAppTimeTracker != r.appTimeTracker) {
...
} else {
startTimeTrackingFocusedActivityLocked();
}
} else {
r.appTimeTracker = null;
}
...
// 將要啟動的Activity移動到前臺
if (mStackSupervisor.moveActivityStackToFront(r, reason + " setFocusedActivity")) {
mWindowManager.setFocusedApp(r.appToken, true);
}
...
return true;
}
這里看一下注釋,主要是判斷該Activity是否有焦點(diǎn)瓦戚,是否允許切換焦點(diǎn)沮尿。因此要結(jié)束的Activity就要把焦點(diǎn)釋放掉。
Step15.ActivityStack.cleanUpActivityServicesLocked
final void cleanUpActivityServicesLocked(ActivityRecord r) {
// Throw away any services that have been bound by this activity.
if (r.connections != null) {
Iterator<ConnectionRecord> it = r.connections.iterator();
while (it.hasNext()) {
ConnectionRecord c = it.next();
mService.mServices.removeConnectionLocked(c, null, r);
}
r.connections = null;
}
}
上面我們提到這個方法主要是釋放綁定的服務(wù)较解,如果沒有則不需要釋放畜疾。下面我們回到Step11中提到的第二步赴邻。
Step16.ApplicationThreadNative.scheduleDestroyActivity
public final void scheduleDestroyActivity(IBinder token, boolean finishing,
int configChanges) throws RemoteException {
...
mRemote.transact(SCHEDULE_FINISH_ACTIVITY_TRANSACTION, data, null,
IBinder.FLAG_ONEWAY);
..
}
這個很熟悉了。
Step17.ApplicationThread.scheduleDestroyActivity
public final void scheduleDestroyActivity(IBinder token, boolean finishing,
int configChanges) {
sendMessage(H.DESTROY_ACTIVITY, token, finishing ? 1 : 0,
configChanges);
}
通過發(fā)送消息到Handler中來處理啡捶。
Step18.ActivityThread.H.handleMessage
public void handleMessage(Message msg) {
switch (msg.what) {
...
case DESTROY_ACTIVITY:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityDestroy");
handleDestroyActivity((IBinder) msg.obj, msg.arg1 != 0,
msg.arg2, false);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
...
Step19.ActivityThread.handleDestroyActivity
private void handleDestroyActivity(IBinder token, boolean finishing,
int configChanges, boolean getNonConfigInstance) {
ActivityClientRecord r = performDestroyActivity(token, finishing,
configChanges, getNonConfigInstance);
...
if (finishing) {
try {
ActivityManagerNative.getDefault().activityDestroyed(token);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
mSomeActivitiesChanged = true;
}
Step20.ActivityThread.performDestroyActivity
private ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing,
int configChanges, boolean getNonConfigInstance) {
ActivityClientRecord r = mActivities.get(token);
Class<? extends Activity> activityClass = null;
if (localLOGV) Slog.v(TAG, "Performing finish of " + r);
if (r != null) {
...
performPauseActivityIfNeeded(r, "destroy");
...
try {
r.activity.mCalled = false;
mInstrumentation.callActivityOnDestroy(r.activity);
...
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {
...
}
}
...
return r;
}
執(zhí)行performPauseActivityIfNeeded姥敛,然后執(zhí)行Instrumentation.callActivityOnDestroy方法結(jié)束。
Step21.ActivityThread.performPauseActivityIfNeeded
private void performPauseActivityIfNeeded(ActivityClientRecord r, String reason) {
if (r.paused) {
// You are already paused silly...
return;
}
try {
r.activity.mCalled = false;
mInstrumentation.callActivityOnPause(r.activity);
...
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {
...
}
r.paused = true;
}
如果已經(jīng)paused了瞎暑,則直接返回徒溪,否則調(diào)用Instrumentation.callActivityOnPause方法。
Step22.Instrumentation.callActivityOnPause
public void callActivityOnPause(Activity activity) {
activity.performPause();
}
Step23.Activity.performPause
final void performPause() {
..
onPause();
...
}
Step24.Activity.onPause
protected void onPause() {
if (DEBUG_LIFECYCLE) Slog.v(TAG, "onPause " + this);
getApplication().dispatchActivityPaused(this);
mCalled = true;
}
這里就是調(diào)用了Activity的onPause方法了金顿。
Step25.Activity.performStop
final void performStop(boolean preserveWindow) {
...
if (!mStopped) {
...
mCalled = false;
mInstrumentation.callActivityOnStop(this);
...
}
mResumed = false;
}
這里調(diào)用Instrumentation.callActivityOnStop方法,這里本來還有Fragment的處理鲤桥,我略掉了揍拆,自己看看。
Step26.Instrumentation.callActivityOnStop
public void callActivityOnStop(Activity activity) {
activity.onStop();
}
這里調(diào)用了Activity的onStop方法茶凳。代碼略了嫂拴。
Step28.Instrumentation.callActivityOnDestroy
public void callActivityOnDestroy(Activity activity) {
...
activity.performDestroy();
...
}
調(diào)用Activity的performDestroy方法
Step29.Activity.performDestroy
final void performDestroy() {
...
onDestroy();
...
}
這里終于看到了onDestroy方法。這里還有Fragment的處理贮喧,我沒有顯示出來筒狠,自己看看。我們再回到Step20中的第二個方法中箱沦。
Step31.AMP.activityDestroyed
public void activityDestroyed(IBinder token) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(token);
mRemote.transact(ACTIVITY_DESTROYED_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);
reply.readException();
data.recycle();
reply.recycle();
}
然后調(diào)用AMS中的activityDestroyed方法辩恼。
Step32.AMS.activityDestroyed
public final void activityDestroyed(IBinder token) {
synchronized (this) {
ActivityStack stack = ActivityRecord.getStackLocked(token);
if (stack != null) {
stack.activityDestroyedLocked(token, "activityDestroyed");
}
}
}
Step33.ActivityStack.activityDestroyedLocked
final void activityDestroyedLocked(IBinder token, String reason) {
final long origId = Binder.clearCallingIdentity();
try {
ActivityRecord r = ActivityRecord.forTokenLocked(token);
...
if (isInStackLocked(r) != null) {
if (r.state == ActivityState.DESTROYING) {
cleanUpActivityLocked(r, true, false);
removeActivityFromHistoryLocked(r, null, reason);
}
}
mStackSupervisor.resumeFocusedStackTopActivityLocked();
} finally {
Binder.restoreCallingIdentity(origId);
}
}
這里主要是兩步,第一個是調(diào)用cleanUpActivityLocked方法谓形,清理Activity灶伊,前面Step12我們分析過了,不再分析寒跳。然后是調(diào)用removeActivityFromHistoryLocked方法聘萨,就是將該結(jié)束的Activity從歷史列表中刪除.
Step35.ActivityStack.removeActivityFromHistoryLocked
// 從歷史記錄移除
private void removeActivityFromHistoryLocked(
ActivityRecord r, TaskRecord oldTop, String reason) {
mStackSupervisor.removeChildActivityContainers(r);
finishActivityResultsLocked(r, Activity.RESULT_CANCELED, null);
...
if (task != null && task.removeActivity(r)) {
if (mStackSupervisor.isFocusedStack(this) && task == topTask &&
task.isOverHomeStack()) {
mStackSupervisor.moveHomeStackTaskToTop(task.getTaskToReturnTo(), reason);
}
removeTask(task, reason);
}
cleanUpActivityServicesLocked(r);
r.removeUriPermissionsLocked();
}
調(diào)用finishActivityResultsLocked方法處理Result,前面提到了童太。調(diào)用ActivityStackSupervisor.moveHomeStackTaskToTop將Home屬性的Activity所在任務(wù)棧放到頂部米辐。調(diào)用cleanUpActivityServicesLocked清理綁定的服務(wù)。
Step39.ActivityStackSupervisor.resumeFocusedStackTopActivityLocked
boolean resumeFocusedStackTopActivityLocked() {
return resumeFocusedStackTopActivityLocked(null, null, null);
}
這里我們在上一章Activity的啟動時已經(jīng)分析過了书释。這里不再分析翘贮。到這里Activity的finish就分析完了,從這里我們主要學(xué)到的是finish的過程爆惧,以及finish過程中系統(tǒng)做了哪些處理择膝,我們在寫代碼過程中應(yīng)該做那些處理。
流程圖:
代碼地址:
直接拉取導(dǎo)入開發(fā)工具(Intellij idea或者Android studio)
注
首發(fā)地址:http://www.codemx.cn
Android開發(fā)群:192508518
微信公眾賬號:Code-MX
注:本文原創(chuàng)检激,轉(zhuǎn)載請注明出處肴捉,多謝腹侣。