上一篇咱們分析了Activity的啓動流程,因爲代碼量很大,仍是沒有分析的很詳細,可是基本流程都出來了,更詳細的東西仍是要去看源碼,源碼在我文章的最後有給出,裏面有我添加的詳細的註釋。這一章來分析Activity的finish過程,這個問題在兩年前我去面試金山的時候曾經被問到過,那時候對源碼基本沒什麼瞭解,因此當時根本是不瞭解的,今天咱們就來分析一下finish的過程到底作了哪些處理,最後對Activity的整個啓動過程以及finish過程繪製流程圖,以方便咱們記憶。java
首先先貼一張時序圖:git
Activity的finish方法就是調用的父類的finish方法:github
public void finish() {
finish(DONT_FINISH_TASK_WITH_ACTIVITY);
}
複製代碼
這裏調用finish方法,傳入參數DONT_FINISH_TASK_WITH_ACTIVITY,這個參數是在finish掉Activity的時候不finish掉Task。面試
private void finish(int finishTask) {
...
if (ActivityManagerNative.getDefault()
.finishActivity(mToken, resultCode, resultData, finishTask)) {
mFinished = true;
}
...
}
複製代碼
ActivityManagerNative.getDefault()方法其實咱們在前面文章提到過,獲得的是AMP(ActivityManagerProxy)。微信
public boolean finishActivity(IBinder token, int resultCode, Intent resultData, int finishTask) throws RemoteException {
...
mRemote.transact(FINISH_ACTIVITY_TRANSACTION, data, reply, 0);
...
}
複製代碼
經過Binder調用AMS的finishActivity方法。app
public final boolean finishActivity(IBinder token, int resultCode, Intent resultData, int finishTask) {
...
synchronized (this) {
// 根據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,因此下面參數是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.requestFinishActivityLockedide
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;
}
複製代碼
調用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;
}
// 標記開始finish
r.makeFinishingLocked();
...
// 中止鍵盤分發事件
r.pauseKeyDispatchingLocked();
adjustFocusedActivityLocked(r, "finishActivity");
finishActivityResultsLocked(r, resultCode, resultData);
// 若是任務中沒有了Activity要結束任務
final boolean endTask = index <= 0;
final int transit = endTask ? TRANSIT_TASK_CLOSE : TRANSIT_ACTIVITY_CLOSE;
if (mResumedActivity == r) {// 若是當前顯示的Activity就是要結束的Activity
...
if (mPausingActivity == null) {
// 開始暫停Activity
startPausingLocked(false, false, null, false);
}
if (endTask) {// 若是任務中沒有了Activity,則移除任務
mStackSupervisor.removeLockedTaskLocked(task);
}
} else if (r.state != ActivityState.PAUSING) {// 若是要移除的Activity不是Pausing狀態而且不是正在顯示的Activity
...
return finishCurrentActivityLocked(r, (r.visible || r.nowVisible) ?
FINISH_AFTER_VISIBLE : FINISH_AFTER_PAUSE, oomAdj) == null;
} else {
...
}
return false;
}
複製代碼
這裏首先調用ActivityRecord.makeFinishingLocked標記開始結束Activity,而後調用ActivityRecord.pauseKeyDispatchingLocked方法中止鍵盤事件分發。而後調用adjustFocusedActivityLocked方法,調整Activity的焦點狀體。開發工具
private void adjustFocusedActivityLocked(ActivityRecord r, String reason) {
// 若是當前棧沒有焦點,或者當前Activity也不是當前有焦點的Activity,返回
if (!mStackSupervisor.isFocusedStack(this) || mService.mFocusedActivity != r) {
return;
}
// 獲取棧頂正在運行的Activity
final ActivityRecord next = topRunningActivityLocked();
final String myReason = reason + " adjustFocus";
if (next != r) {// 若是棧頂正在運行的不是當前要結束的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);
}
複製代碼
當前Activity要finish掉,就找找到下一個應該獲取焦點的Activity,在該Activity被finish掉以後顯示出來。ui
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相關信息封裝成ActivityResult對象放到ActivityResult列表中保存起來。而後置空該Activity對應的ActivityRecord對象中的信息。
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狀態
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);
}
...
// 改變狀態
prev.state = ActivityState.PAUSING;
...
// 獲取正在啓動的Activity組件
final ActivityRecord next = mStackSupervisor.topRunningActivityLocked();
...
if (prev.app != null && prev.app.thread != null) {
...
// 通知源Activity組件,暫停源Activity以便有機會執行一些數據保存操做,
// 這裏若是目標sdk<11會調用onSaveInstanceState,而後調用onPause
prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
userLeaving, prev.configChangeFlags, dontWait);
...
} else {
...
}
...
}
複製代碼
這裏主要是在finish以前pause該Activity,若是狀態正常會調用schedulePauseActivity方法,最終調用Activity的onPause方法,這個過程咱們在前面講過幾回了,這裏就再也不分析,比較簡單。咱們接着看核心的代碼。
final ActivityRecord finishCurrentActivityLocked(ActivityRecord r, int mode, boolean oomAdj) {
// 若是當前要finish的Activity正在顯示,而複用的Activity尚未顯示,那麼延遲finish,
// 直到複用Activity顯示
// 獲取頂部正在運行的Activity
final ActivityRecord next = mStackSupervisor.topRunningActivityLocked();
// 若是是顯示後在finish,而且要結束的正在顯示或者將要顯示,而且頂部運行的存在並且沒有顯示
if (mode == FINISH_AFTER_VISIBLE && (r.visible || r.nowVisible)
&& next != null && !next.nowVisible) {
// 若是當前要結束的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;// 存儲清理以前的狀態
r.state = ActivityState.FINISHING;// 設置爲正在finish狀態
// 判斷當前正在清理的Activity是否在當前獲取焦點的棧中
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,首先要保存狀態,而後標記開始finish,而後調用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。咱們先看第一步。
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) {// 是否清理服務
cleanUpActivityServicesLocked(r);
}
...
}
複製代碼
這裏主要是將指向該銷燬的Activity的引用都置空,進行釋放,而後將該Activity描述對象從列表中移除該對象,最後是判斷是否清理服務,其實主要是綁定該Activity的服務,若是有綁定則解除綁定。
// 從新設置獲取焦點的Activity,若是被清理的不是獲取焦點的,那麼不處理,不然將焦點移動到另一個Activity
final void resetFocusedActivityIfNeededLocked(ActivityRecord goingAway) {
...
// Try to move focus to another activity if possible.
// 若是容許,將焦點移動到另一個Activity
if (setFocusedActivityLocked(
focusedStack.topRunningActivityLocked(), "resetFocusedActivityIfNeeded")) {
return;
}
...
}
複製代碼
這裏調用setFocusedActivityLocked方法判斷該Activity是否是容許容許將焦點移除。
boolean setFocusedActivityLocked(ActivityRecord r, String reason) {
if (r == null || mFocusedActivity == r) {// 若是傳入的焦點Activity不存在或者就是顯示在有焦點的Activity則不須要處理了
return false;
}
if (!r.isFocusable()) {// 若是沒有獲取焦點,返回
return false;
}
...
// 獲取以前有焦點的Activity
final ActivityRecord last = mFocusedActivity;
mFocusedActivity = r;// 設置傳入的Activity爲當前焦點Activity
if (r.task.isApplicationTask()) {// 當前焦點Activity所在任務是應用任務(不是桌面和最近應用界面)
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是否有焦點,是否容許切換焦點。所以要結束的Activity就要把焦點釋放掉。
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;
}
}
複製代碼
上面咱們提到這個方法主要是釋放綁定的服務,若是沒有則不須要釋放。下面咱們回到Step11中提到的第二步。
public final void scheduleDestroyActivity(IBinder token, boolean finishing, int configChanges) throws RemoteException {
...
mRemote.transact(SCHEDULE_FINISH_ACTIVITY_TRANSACTION, data, null,
IBinder.FLAG_ONEWAY);
..
}
複製代碼
這個很熟悉了。
public final void scheduleDestroyActivity(IBinder token, boolean finishing, int configChanges) {
sendMessage(H.DESTROY_ACTIVITY, token, finishing ? 1 : 0,
configChanges);
}
複製代碼
經過發送消息到Handler中來處理。
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;
...
複製代碼
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;
}
複製代碼
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;
}
複製代碼
執行performPauseActivityIfNeeded,而後執行Instrumentation.callActivityOnDestroy方法結束。
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;
}
複製代碼
若是已經paused了,則直接返回,不然調用Instrumentation.callActivityOnPause方法。
public void callActivityOnPause(Activity activity) {
activity.performPause();
}
複製代碼
final void performPause() {
..
onPause();
...
}
複製代碼
protected void onPause() {
if (DEBUG_LIFECYCLE) Slog.v(TAG, "onPause " + this);
getApplication().dispatchActivityPaused(this);
mCalled = true;
}
複製代碼
這裏就是調用了Activity的onPause方法了。
final void performStop(boolean preserveWindow) {
...
if (!mStopped) {
...
mCalled = false;
mInstrumentation.callActivityOnStop(this);
...
}
mResumed = false;
}
複製代碼
這裏調用Instrumentation.callActivityOnStop方法,這裏原本還有Fragment的處理,我略掉了,本身看看。
public void callActivityOnStop(Activity activity) {
activity.onStop();
}
複製代碼
這裏調用了Activity的onStop方法。代碼略了。
public void callActivityOnDestroy(Activity activity) {
...
activity.performDestroy();
...
}
複製代碼
調用Activity的performDestroy方法
final void performDestroy() {
...
onDestroy();
...
}
複製代碼
這裏終於看到了onDestroy方法。這裏還有Fragment的處理,我沒有顯示出來,本身看看。咱們再回到Step20中的第二個方法中。
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();
}
複製代碼
而後調用AMS中的activityDestroyed方法。
public final void activityDestroyed(IBinder token) {
synchronized (this) {
ActivityStack stack = ActivityRecord.getStackLocked(token);
if (stack != null) {
stack.activityDestroyedLocked(token, "activityDestroyed");
}
}
}
複製代碼
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);
}
}
複製代碼
這裏主要是兩步,第一個是調用cleanUpActivityLocked方法,清理Activity,前面Step12咱們分析過了,再也不分析。而後是調用removeActivityFromHistoryLocked方法,就是將該結束的Activity從歷史列表中刪除.
// 從歷史記錄移除
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();
}
複製代碼
調用finishActivityResultsLocked方法處理Result,前面提到了。調用ActivityStackSupervisor.moveHomeStackTaskToTop將Home屬性的Activity所在任務棧放到頂部。調用cleanUpActivityServicesLocked清理綁定的服務。
boolean resumeFocusedStackTopActivityLocked() {
return resumeFocusedStackTopActivityLocked(null, null, null);
}
複製代碼
這裏咱們在上一章Activity的啓動時已經分析過了。這裏再也不分析。到這裏Activity的finish就分析完了,從這裏咱們主要學到的是finish的過程,以及finish過程當中系統作了哪些處理,咱們在寫代碼過程當中應該作那些處理。
直接拉取導入開發工具(Intellij idea或者Android studio)
首發地址:www.codemx.cn
Android開發羣:192508518
微信公衆帳號:Code-MX
注:本文原創,轉載請註明出處,多謝。