---
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 之前被呼叫
> 
```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 之前被呼叫
> 
```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 生命週期整理
> 
## Appendix & FAQ
:::info
:::
###### tags: `Android Framework`