--- title: 'Activity 狀態 - 儲存時機' disqus: kyleAlien --- Activity 狀態 - 儲存時機 === ## OverView of Content Activity 被系統強制回收時,會觸發 `onSaveInstanceState`,再次開啟時又會觸發 `onRestoreInstanceState` 生命週期 其主要設計是使用了 [**Memo 設計模式**](https://hackmd.io/sLPWDFoqQJW39j2QgNFbZg?view#OverView-of-Content) (請點連結查看),這裡主要分析這兩個生命週期被觸發的時機點 [TOC] ## AMS 與 Activity 狀態關係 系統在回收指定 App 之前,會將該應用的 Activity 狀態傳給 AMS 儲存,在需要恢復時再透過 AMS 傳遞儲存好的訊息給 App ### [Activity](https://cs.androidom/android/platform/superproject/+/master:frameworks/base/core/java/android/app/Activity.java) 呼叫 onSaveInstanceState 時機 * AMS 在需要暫停 Activity 時會透過 [**ClientTransactionHandler**](https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/app/ClientTransactionHandler.java)(抽象) 控制,在 Pause 時會呼叫 ClientTransactionHandler#`handlePauseActivity` 方法 ```java= // ActivityThread.java @Override public void handlePauseActivity(ActivityClientRecord r, boolean finished, boolean userLeaving, int configChanges, PendingTransactionActions pendingActions, String reason) { if (userLeaving) { performUserLeavingActivity(r); } r.activity.mConfigChangeFlags |= configChanges; performPauseActivity(r, finished, reason, pendingActions); // Make sure any pending writes are now committed. if (r.isPreHoneycomb()) { QueuedWork.waitToFinish(); } mSomeActivitiesChanged = true; } ``` * **performStopActivityInner 方法**:從這裡就可以看出,Activity#onSaveInstanceState 方法會在 Activity#onPause 之前被呼叫 > ![](https://i.imgur.com/VcgYz9z.png) ```java= // ActivityThread.java private Bundle performPauseActivity(ActivityClientRecord r, boolean finished, String reason, PendingTransactionActions pendingActions) { if (r.paused) { if (r.activity.mFinished) { // Activity 已經 Finish,則不進行多於操作 return null; } RuntimeException e = new RuntimeException( "Performing pause of activity that is not resumed: " + r.intent.getComponent().toShortString()); Slog.e(TAG, e.getMessage(), e); } if (finished) { r.activity.mFinished = true; } // Pre-Honeycomb apps always save their state before pausing final boolean shouldSaveState = !r.activity.mFinished && r.isPreHoneycomb(); // 狀態儲存 if (shouldSaveState) { callActivityOnSaveInstanceState(r); } // onPause 方法 performPauseActivityIfNeeded(r, reason); ... 省略部分 return shouldSaveState ? r.state : null; } ``` 最終 **透過 Instrumentation 呼叫到 Activity#onSaveInstanceState 方法** ```java= // Instrumentation.java private void callActivityOnSaveInstanceState(ActivityClientRecord r) { // 將新的 Bundle 資料存到 ActivityClientRecord 中 r.state = new Bundle(); r.state.setAllowFds(false); if (r.isPersistable()) { r.persistentState = new PersistableBundle(); mInstrumentation.callActivityOnSaveInstanceState(r.activity, r.state, r.persistentState); } else { mInstrumentation.callActivityOnSaveInstanceState(r.activity, r.state); } } ``` ### [Activity](https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/app/Activity.java) 呼叫 onRestoreInstanceState 時機 * AMS 在需要啟動 Activity 時會透過 [**ClientTransactionHandler**](https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/app/ClientTransactionHandler.java)(抽象) 控制,在 Start 時會呼叫 ClientTransactionHandler#`handleStartActivity` 方法 * **performLaunchActivity 方法**:從這裡就可以看出,Activity#onRestoreInstanceState 方法會在 Activity#onStart 之前被呼叫 > ![](https://i.imgur.com/ySgSeMZ.png) ```java= // ActivityThread.java @Override public void handleStartActivity(ActivityClientRecord r, PendingTransactionActions pendingActions, ActivityOptions activityOptions) { final Activity activity = r.activity; if (!r.stopped) { // 只有 stop 狀態才可以呼叫 start throw new IllegalStateException("Can't start activity that is not stopped."); } // Activity finish 則返回 if (r.activity.mFinished) { // TODO(lifecycler): How can this happen? return; } ... // 呼叫 Activity#onStart 方法 activity.performStart("handleStartActivity"); r.setState(ON_START); // Restore instance state if (pendingActions.shouldRestoreInstanceState()) { if (r.isPersistable()) { ... } else if (r.state != null) { mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state); } } ... 省略部分 } ``` 最終 **透過 Instrumentation 呼叫到 Activity#onSaveInstanceState 方法** ```java= // Instrumentation.java public void callActivityOnRestoreInstanceState(@NonNull Activity activity, @NonNull Bundle savedInstanceState) { activity.performRestoreInstanceState(savedInstanceState); } ``` ### Activity 生命週期整理 > ![](https://i.imgur.com/otgYiit.png) ## Appendix & FAQ :::info ::: ###### tags: `Android Framework`