首先咱們來看一下finish方法的無參版本的定義:java
/** * Call this when your activity is done and should be closed. The * ActivityResult is propagated back to whoever launched you via * onActivityResult(). */ public void finish() { finish(false); }
根據源碼中的註釋咱們能夠知道,當咱們的activity已經完成它的工做,咱們想要關閉它時,咱們能夠調用finish()方法。這個方法內部回去調用finish(boolean)方法,並傳入false做爲參數。那麼接下來咱們從finish(boolean)方法出發,來了解下finish()方法的大體執行流程。android
1 /** 2 * Finishes the current activity and specifies whether to remove the task associated with this 3 * activity. 4 */ 5 private void finish(boolean finishTask) { 6 if (mParent == null) { 7 int resultCode; 8 Intent resultData; 9 synchronized (this) { 10 resultCode = mResultCode; 11 resultData = mResultData; 12 } 13 if (false) Log.v(TAG, "Finishing self: token=" + mToken); 14 try { 15 if (resultData != null) { 16 resultData.prepareToLeaveProcess(); 17 } 18 if (ActivityManagerNative.getDefault() 19 .finishActivity(mToken, resultCode, resultData, finishTask)) { 20 mFinished = true; 21 } 22 } catch (RemoteException e) { 23 // Empty 24 } 25 } else { 26 mParent.finishFromChild(this); 27 } 28 }
根據註釋咱們能夠知道boolean類型參數finishTask的做用是是否移除與咱們要關閉的activity相關聯的task。咱們注意到這個方法的訪問修飾符是private,因此它只是供Activity類內部調用的方法。那麼咱們接下來看一下這個方法到底是怎樣實現關閉一個activity的。在第6行,咱們判斷mParent是否爲null。如今咱們只須要知道mParent在通常狀況下均爲null便可。因此這個方法接下來會執行第7到24行的代碼。在第10行和第11行,咱們分別把resultCode和resultData賦值爲mResultCode和mResultData。resultCode和resultData最終會傳入到onActivityResult方法中。app
以上代碼的關鍵在於第18行調用的finishActivity方法,若這個方法返回true,咱們就會設置Activity的mFinished成員變量爲true。isFinishing()方法用於判斷一個Activity是否處於銷燬狀態,這個方法的實現就是返回mFinished成員變量。也就是說,若finishActivity方法執行完畢並返回true,則Activity就被成功銷燬了。下面咱們回到第18行:經過調用ActivityManagerNative.getDefault()方法會獲得一個ActivityManagerProxy對象,這是ActivityManagerService(下文簡稱爲AMS)的代理對象。那麼AMS是什麼呢?這裏咱們只須要知道它是一個系統服務,系統中四大組件的啓動、切換、銷燬等都是由它負責的。咱們經過ActivityManagerProxy對象能夠請求AMS去啓動、暫停或是銷燬一個Activity。ActivityManagerProxy是ActivityManagerNative的一個內部類,它的finishActivity方法以下所示:oop
1 public boolean finishActivity(IBinder token, int resultCode, Intent resultData, boolean finishTask) 2 throws RemoteException { 3 Parcel data = Parcel.obtain(); 4 Parcel reply = Parcel.obtain(); 5 data.writeInterfaceToken(IActivityManager.descriptor); 6 data.writeStrongBinder(token); 7 data.writeInt(resultCode); 8 if (resultData != null) { 9 data.writeInt(1); 10 resultData.writeToParcel(data, 0); 11 } else { 12 data.writeInt(0); 13 } 14 data.writeInt(finishTask ? 1 : 0); 15 mRemote.transact(FINISH_ACTIVITY_TRANSACTION, data, reply, 0); 16 reply.readException(); 17 boolean res = reply.readInt() != 0; 18 data.recycle(); 19 reply.recycle(); 20 return res; 21 }
以上代碼中的reply用於保存返回結果,data會做爲參數傳遞給AMS。咱們首先向要傳遞給AMS的data中寫入了token、resultCode。若resultData不爲null,則會先寫入一個整數1,再寫入resultData,若resultData爲null,則只寫入一個整數0。而後咱們再根據finishTask參數爲true或false分別寫入1或0。以上代碼的關鍵在於第15行調用的mRemote.transact(...)方法,它會致使AMS的onTransact(...)方法被調用。AMS的onTransact方法調用了ActivityManagerNative的onTransact方法,這個方法的代碼以下:this
public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { switch (code) { ... case FINISH_ACTIVITY_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); IBinder token = data.readStrongBinder(); Intent resultData = null; int resultCode = data.readInt(); if (data.readInt() != 0) { resultData = Intent.CREATOR.createFromParcel(data); } boolean finishTask = (data.readInt() != 0); boolean res = finishActivity(token, resultCode, resultData, finishTask); reply.writeNoException(); reply.writeInt(res ? 1 : 0); return true; } ... }
咱們能夠看到,這個方法會根據傳入的code參數執行不一樣的case分支,這裏會執行的是code爲FINISH_ACTIVITY_TRANSACTION的分支。以上代碼中又調用了finishActivity方法(AMS中),因此咱們接着看這個方法的實現:google
1 /** 2 * This is the internal entry point for handling Activity.finish(). 3 * 4 * @param token The Binder token referencing the Activity we want to finish. 5 * @param resultCode Result code, if any, from this Activity. 6 * @param resultData Result data (Intent), if any, from this Activity. 7 * 8 * @return Returns true if the activity successfully finished, or false if it is still running. 9 */ 10 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) { 11 // Refuse possible leaked file descriptors 12 if (resultData != null && resultData.hasFileDescriptors() == true) { 13 throw new IllegalArgumentException("File descriptors passed in Intent"); 14 } 15 synchronized(this) { 16 ...33 final long origId = Binder.clearCallingIdentity(); 17 boolean res = requestFinishActivityLocked(token, resultCode, 18 resultData, "app-request"); 19 Binder.restoreCallingIdentity(origId); 20 return res; 21 } 22 }
根據源碼中的註釋咱們能夠看到,這個方法是處理Activity.finish()的內部入口點。這個方法內部又調用了requestFinishActivityLocked方法,因此咱們還要接着跟進。requestFinishActivityLocked方法的源碼以下:spa
1 private final boolean requestFinishActivityLocked(IBinder token, int resultCode, 2 Intent resultData, String reason) { 3 ... 4 HistoryRecord r = (HistoryRecord)mHistory.get(index); 5 // Is this the last activity left? 6 boolean lastActivity = true; 7 for (int i=mHistory.size()-1; i>=0; i--) { 8 HistoryRecord p = (HistoryRecord)mHistory.get(i); 9 if (!p.finishing && p != r) { 10 lastActivity = false; 11 break; 12 } 13 } 14 15 // If this is the last activity, but it is the home activity, then 16 // just don't finish it. 17 if (lastActivity) { 18 if (r.intent.hasCategory(Intent.CATEGORY_HOME)) { 19 return false; 20 } 21 } 22 23 finishActivityLocked(r, index, resultCode, resultData, reason); 24 return true; 25 }
首先咱們看一下第4行出現了HistoryRecord和mHistory。這裏咱們簡單的介紹一下它們兩個。mHistory是AMS的成員變量,它是一個ArrayList,裏面存儲的元素類型爲HistoryRecord,一個HistoryReord表示一個Activity。也就是說mHistory存儲了系統中全部曾經存在過或正在運行的Activity。第6行到第13行的功能就是判斷如今系統中是否只剩下一個正在運行Activity,這一點從註釋中就能夠看出。而後在第17行到第21行,若惟一正在運行的Activity是HomeActivity,則直接返回false(不會關閉它)。以上代碼中的關鍵在於第23行調用的finishActivityLocked方法,這個方法的核心代碼以下:線程
private final boolean finishActivityLocked(HistoryRecord r, int index, int resultCode, Intent resultData, String reason) { ...if (mResumedActivity == r) { ... } 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, "Finish not pausing: " + r); return finishCurrentActivityLocked(r, index, FINISH_AFTER_PAUSE) == null; } else { if (DEBUG_PAUSE) Slog.v(TAG, "Finish waiting for pause of: " + r); } return false; }
以上代碼實際上會調用finishCurrentActivityLocked方法,若這個方法返回值爲null,finishActivityLocked則會返回true,不然會返回false。那麼咱們來看看finishCurrentActivityLocked方法的實現:代理
private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r, int index, int mode) { ...
final ActivityState prevState = r.state; r.state = ActivityState.FINISHING; if (mode == FINISH_IMMEDIATELY || prevState == ActivityState.STOPPED || prevState == ActivityState.INITIALIZING) { // If this activity is already stopped, we can just finish // it right now. return destroyActivityLocked(r, true) ? null : r; } else { // Need to go through the full pause cycle to get this // activity into the stopped state and then finish it. if (localLOGV) Slog.v(TAG, "Enqueueing pending finish: " + r); mFinishingActivities.add(r); resumeTopActivityLocked(null); } return r; }
根據源碼中的註釋咱們能夠知道,若Activity已經處於中止狀態,則能夠當即調用destroyActivityLocked方法;不然咱們須要先經歷完整的「暫停週期」以讓這個Activity處於中止狀態後再結束它。rest
在destroyActivityLocked方法中存在以下這句代碼:
r.app.thread.scheduleDestroyActivity(r, r.finishing,r.configChangeFlags);
其中,r.app.thread其實是AMS持有的應用程序進程的ApplicationThread的代理對象,因此實際上調用的是ApplicationThread的scheduleDestroyActivity方法,然後這個方法中會向主線程(ActivityThread)發送一個H.DESTROY_ACTIVITY消息,主線程會調用handleDestroyActivity來處理這個消息,再通過層層調用後,Activity的onDestroy方法會被回調。對這一過程感興趣的同窗能夠自行閱讀相關源碼。
經過上面對源碼的分析,咱們大概瞭解了finish()方法的工做流程,有兩點須要咱們注意:
(1)通過層層調用,ApplicationThread.scheduleDestroyActivity方法會被調用,這個方法會完成對Activity的銷燬工做,而且會回調Activity.onDestroy()方法。因此咱們知道了調用finish()方法會致使對Acitivity的銷燬,從而致使Activity.onDestroy()被回調。
(2)在咱們的平常開發中,每每會將finish()方法的調用包含在Activity的某個生命週期中,而實際上Activity的各個生命週期方法都是由ApplicationThread.scheduleXXXActivity方法回調的,這個方法會向主線程發送一個H.XXX_ACTIVITY消息,隨後主線程的Looper會從消息隊列中這個消息並調用handleXXXActivity方法來處理它,並最終會回到Activity.onXXX方法。好比咱們在onCreate()方法中調用了finish()方法,那麼因爲此時主線程正處於對H.CREATE_ACTIVITY消息的處理中,因此暫時沒法處理H.DESTROY_ACTIVITY消息,只有當主線程處理完前一個消息了,纔會着手處理H_DESTROY_ACTIVITY消息。所以,咱們調用finish()方法後,onDestroy()每每並不會被當即調用,可是咱們能夠經過isFinishing()方法來判斷Activity是否處於銷燬狀態。
以上是我對finish()方法相關源碼的執行流程的總結,因爲我的水平有限,敘述中不免存在不許確或是不清晰的地方,但願你們能夠指出,謝謝你們:)
https://android.googlesource.com/platform/frameworks/base/+/android-6.0.1_r26/core/java/android/app