【和訳】Lifecycle-Aware Components(Codelabs for the 2019 Android Dev Summit: Mountain View, October 23-24, 2019.)

[Android Dev Summit 2019
Codelabs for the 2019 Android Dev Summit: Mountain View, October 23-24, 2019.](https://codelabs.developers.google.com/ads19/)

[Lifecycle-Aware Components](https://codelabs.developers.google.com/codelabs/android-lifecycles/index.html?index=..%2F..ads19#0)の日本語訳

# 1.はじめに
## 構成部品
[アーキテクチャコンポーネント](https://developer.android.com/topic/libraries/architecture/index.html)は、堅牢、テスト可能、保守可能な方法でアプリを構築するのに役立つAndroidライブラリのセットです。
このコードラボでは、Androidアプリを構築するための次のライフサイクル対応アーキテクチャコンポーネントを紹介します。

- **ViewModel**－特定のライフサイクルにバインドされたオブジェクトを作成および取得する方法を提供します。[*ViewModel*](https://developer.android.com/reference/android/arch/lifecycle/ViewModel.html)は通常、ビューのデータの状態を保存し、データリポジトリやビジネスロジックを処理するドメインレイヤーなどの他のコンポーネントと通信します。このトピックの入門ガイドを読むには、[*ViewModel*](https://developer.android.com/topic/libraries/architecture/viewmodel.html)を参照してください。
- **LifecycleOwner**－*[LifecycleOwner](https://developer.android.com/reference/androidx/lifecycle/LifecycleOwner.html)*は、*[AppCompatActivity](https://developer.android.com/reference/androidx/appcompat/app/AppCompatActivity)*および*[Fragment](https://developer.android.com/reference/androidx/fragment/app/Fragment)*クラスによって実装されるインターフェイスです。このインターフェイスを実装する所有者オブジェクトに他のコンポーネントをサブスクライブして、所有者のライフサイクルの変更を観察できます。このトピックの入門ガイドを読むには、[ライフサイクルの処理](https://developer.android.com/topic/libraries/architecture/lifecycle.html)を参照してください。
- **LiveData**－明示的で厳密な依存関係のパスを作成することなく、アプリの複数のコンポーネントにわたるデータの変更を観察できます。[*LiveData*](https://developer.android.com/reference/android/arch/lifecycle/LiveData.html)は、アクティビティ、フラグメント、サービス、またはアプリで定義された[*LifecycleOwner*](https://developer.android.com/reference/android/arch/lifecycle/LifecycleOwner.html)など、アプリコンポーネントの複雑なライフサイクルを尊重します。[*LiveData*](https://developer.android.com/reference/android/arch/lifecycle/LiveData.html)は、停止した[*LifecycleOwner*](https://developer.android.com/reference/android/arch/lifecycle/LifecycleOwner.html)オブジェクトへのサブスクリプションを一時停止し、終了した[*LifecycleOwner*](https://developer.android.com/reference/android/arch/lifecycle/LifecycleOwner.html)オブジェクトへのサブスクリプションをキャンセルすることにより、オブザーバーサブスクリプションを管理します。このトピックの入門ガイドを読むには、[*LiveData*](https://developer.android.com/topic/libraries/architecture/livedata.html)を参照してください。

## 構築するもの
このコードラボでは、上記の各コンポーネントの例を実装します。サンプルアプリから始めて、一連の手順でコードを追加し、進行に応じてさまざまなアーキテクチャコンポーネントを統合します。

## 必要なもの

- Android Studio 3.5以降
- Androidアクティビティのライフサイクルに精通している

# 2.ステップ1-環境のセットアップ
この手順では、コードラボ全体のコードをダウンロードしてから、簡単なサンプルアプリを実行します。

```console
$ git clone git@github.com:googlecodelabs/android-lifecycles.git
```

または、リポジトリをZipファイルとしてダウンロードできます。

[ソースコードをダウンロード](https://github.com/googlecodelabs/android-lifecycles/archive/master.zip)

コードを入手したら

　　1. プロジェクトAndroid Studioバージョン2.5以降を開きます。
　　2. コードルートディレクトリから、このコードラボで使用されるAndroid Studio実行構成をコピーします。

MacOS / Linux:

```console
mkdir -p .idea/runConfigurations
cp runConfigurations/* .idea/runConfigurations/
```

Windows:

```console
MKDIR .idea\runConfigurations
COPY runConfigurations\* .idea\runConfigurations\
```

コマンドを実行すると、各ステップの実行構成が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170755/c70eb57a-48fb-a0ad-ecfd-979a14b2b17c.png)

　　3. デバイスまたはエミュレータでステップ1の構成を実行します。

アプリが実行され、次のスクリーンショットのような画面が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170755/5f451808-cfc1-0cd1-8545-1e63e6af2e93.png)

　　4. 画面を回転させて、タイマーがリセットされることに注意してください！

> Android 8.0以降を実行しているエミュレーターまたはデバイスを使用している場合は、設定で回転を有効にする必要があります。
> ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170755/999fd0c9-e349-dc6b-e785-5df5ca574fc0.png)

次に、アプリを更新して、画面の回転が変わっても状態を維持する必要があります。このクラスのインスタンスは、画面の回転などの構成の変更に耐えるため、*ViewModel*を使用できます。

# 3.ステップ2-ViewModelを追加する
このステップでは、*ViewModel*を使用して、画面の回転をまたいで状態を維持し、前のステップで観察した動作に対処します。前のステップでは、タイマーを表示するアクティビティを実行しました。このタイマーは、画面の回転などの構成の変更によりアクティビティが破壊されるとリセットされます。
*ViewModel*を使用して、アクティビティまたはフラグメントのライフサイクル全体にわたってデータを保持できます。前のステップが示すように、アクティビティはアプリデータを管理するのに適切な選択肢ではありません。アクティビティとフラグメントは、ユーザーがアプリを操作するたびに頻繁に作成および破棄される短命のオブジェクトです。*ViewModel*は、ネットワーク通信に関連するタスクの管理、およびデータの操作と永続化にも適しています。

## ViewModelを使用してクロノメーターの状態を永続化する
*ChronoActivity2*を開き、クラスが*ViewModel*を取得して使用する方法を調べます。

```java
ChronometerViewModel chronometerViewModel
                = new ViewModelProvider(this).get(ChronometerViewModel.class);
```

これは、*LifecycleOwner*のインスタンスを指します。*LifecycleOwner*のスコープが有効である限り、フレームワークは*ViewModel*を有効に保ちます。画面の回転などの構成変更のために所有者が破棄された場合、*ViewModel*は破棄されません。次の図に示すように、所有者の新しいインスタンスは既存の*ViewModel*に再接続します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170755/85d433e5-3032-42a2-9b6b-07c1f2b8a8d9.png)

> **注意**：アクティビティまたはフラグメントのスコープは、作成から終了（または終了した）に移行します。これは、破壊と混同しないでください。デバイスが回転すると、アクティビティは破棄されますが、それに関連付けられている*ViewModel*のインスタンスは破棄されないことに注意してください。

# やってみて
アプリを実行し（[実行構成]ドロップダウンでステップ2を選択）、次のいずれかのアクションを実行したときにタイマーがリセットされないことを確認します。

　　1. 画面を回転させます
　　2. 別のアプリに移動してから戻ります

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170755/3050b099-e1aa-78ef-30c5-ff92d3f804a6.png)
ただし、ユーザーまたはシステムがアプリを終了すると、タイマーがリセットされます。

> **注意**：システムは、フラグメントやアクティビティなどのライフサイクル所有者のライフサイクル全体にわたって、*ViewModel*のインスタンスをメモリに保持します。システムは*ViewModel*のインスタンスを長期ストレージに永続化しません。

# 4.ステップ3-LiveDataを使用してデータをラップする
この手順では、前の手順で使用したクロノメーターを、[*Timer*](https://developer.android.com/reference/java/util/Timer.html)を使用するカスタムのものに置き換え、UIを毎秒更新します。[*Timer*](https://developer.android.com/reference/java/util/Timer.html)は、繰り返しタスクをスケジュールするために使用できる*java.util*クラスです。このロジックを*LiveDataTimerViewModel*クラスに追加し、アクティビティを残して、ユーザーとUI間の対話の管理に集中します。

タイマーによって通知されると、アクティビティはUIを更新します。メモリリークを防ぐため、[*ViewModel*](https://developer.android.com/reference/android/arch/lifecycle/ViewModel.html)にはアクティビティへの参照が含まれていません。たとえば、画面の回転などの構成の変更により、ガベージコレクションが必要なアクティビティへの[*ViewModel*](https://developer.android.com/reference/android/arch/lifecycle/ViewModel.html)の参照が発生する場合があります。システムは、対応するアクティビティまたはライフサイクルの所有者が存在しなくなるまで、[*ViewModel*](https://developer.android.com/reference/android/arch/lifecycle/ViewModel.html)のインスタンスを保持します。

> **注意**：*ViewModel*に[コンテキスト](https://developer.android.com/reference/android/content/Context.html)または[ビュー](https://developer.android.com/reference/android/view/View.html)への参照を保存すると、メモリリークが発生する可能性があります。*Context*クラスまたは*View*クラスのインスタンスを参照するフィールドは避けてください。[*onCleared()*](https://developer.android.com/reference/android/arch/lifecycle/ViewModel.html#onCleared())メソッドは、ライフサイクルが長い他のオブジェクトへの参照をサブスクライブ解除またはクリアするのに役立ちますが、*Context*オブジェクトまたは*View*オブジェクトへの参照をクリアするためには役立ちません。

[*ViewModel*](https://developer.android.com/reference/android/arch/lifecycle/ViewModel.html)からビューを直接変更する代わりに、アクティビティまたはフラグメントを構成して、データソースを監視し、変更時にデータを受信します。この配置は、オブザーバーパターンと呼ばれます。

> **注**：データをオブザーバブルとして公開するには、*LiveData*クラスで型をラップします。

[データバインディングライブラリ](https://developer.android.com/topic/libraries/data-binding/index.html)、または*RxJava*のような他のリアクティブライブラリを使用したことがある場合は、オブザーバーパターンに慣れているかもしれません。[*LiveData*](https://developer.android.com/reference/android/arch/lifecycle/LiveData.html)は、ライフサイクルに対応した特別なオブザーバブルクラスであり、アクティブなオブザーバーにのみ通知します。

## LifecycleOwner
*ChronoActivity3*は、[*ComponentActivity*](https://developer.android.com/reference/androidx/appcompat/app/AppCompatActivity)のサブクラスである[*AppCompatActivity*](https://developer.android.com/reference/androidx/activity/ComponentActivity.html)のインスタンスです。リファレンスドキュメントを見て、*ComponentActivity*が[*LifecycleOwner*](https://developer.android.com/reference/androidx/lifecycle/LifecycleOwner.html)を実装していることに注意してください。
[*LifecycleOwner*](https://developer.android.com/reference/androidx/lifecycle/LifecycleOwner.html)は、Androidライフサイクルを持つすべてのクラスで使用されるインターフェースです。実際には、クラスにライフサイクルを表す[Lifecycle](https://developer.android.com/reference/androidx/lifecycle/Lifecycle.html)オブジェクトがあることを意味します。
[*ViewModel*](https://developer.android.com/reference/android/arch/lifecycle/ViewModel.html)と[*LiveData*](https://developer.android.com/reference/android/arch/lifecycle/LiveData.html)の両方がライフサイクルにバインドできます。

## ChronoActivityを更新する
　1. subscribe（）メソッドでChronoActivity3クラスに次のコードを追加して、サブスクリプションを作成します。

```java
mLiveDataTimerViewModel.getElapsedTime().observe(this, elapsedTimeObserver);
```

　2. 次に、LiveDataTimerViewModelクラスで新しい経過時間値を設定します。 次のコメントを見つけます。

```java
//TODO post the new value with LiveData.postValue()
```

コメントを次の文に置き換えます。

```java
mElapsedTime.postValue(newValue);
```

　3. アプリを実行し、Android StudioでLogcatを開きます。別のアプリに移動しない限り、ログは毎秒更新されることに注意してください。お使いのデバイスがマルチウィンドウモードをサポートしている場合は、使用してみてください。画面を回転しても、アプリの動作には影響しません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170755/5f8fb383-1a53-a015-3220-b2bd1f0bf352.png)

> **注**：*LiveData*オブジェクトは、アクティビティまたは*LifecycleOwner*がアクティブな場合にのみ更新を送信します。別のアプリに移動すると、戻るまでログメッセージが一時停止します。*LiveData*オブジェクトは、それぞれのライフサイクル所有者が[*STARTED*](https://developer.android.com/reference/android/arch/lifecycle/Lifecycle.State.html#started)または[*RESUMED*](https://developer.android.com/reference/android/arch/lifecycle/Lifecycle.State.html#resumed)の場合にのみ、サブスクリプションがアクティブであると見なします。

# 5.ステップ4-ライフサイクルイベントの講読
多くのAndroidコンポーネントとライブラリでは、次のことが必要です。

　　1. コンポーネントまたはライブラリを講読または初期化します。
　　2. コンポーネントまたはライブラリを講読解除または停止します。

上記の手順を完了しないと、メモリリークや微妙なバグが発生する可能性があります。
ライフサイクル所有者オブジェクトをライフサイクル対応コンポーネントの新しいインスタンスに渡して、ライフサイクルの現在の状態を確実に把握できます。
次のステートメントを使用して、ライフサイクルの現在の状態を照会できます。

```java
lifecycleOwner.getLifecycle().getCurrentState()
```

上記のステートメントは、[*Lifecycle.State.RESUMED*](https://developer.android.com/reference/android/arch/lifecycle/Lifecycle.State.html#resumed)や[*Lifecycle.State.DESTROYED*](https://developer.android.com/reference/android/arch/lifecycle/Lifecycle.State.html#destroyed)などの状態を返します。
[*LifecycleObserver*](https://developer.android.com/reference/android/arch/lifecycle/LifecycleObserver.html)を実装するライフサイクル対応オブジェクトは、ライフサイクル所有者の状態の変化も監視できます。

```java
lifecycleOwner.getLifecycle().addObserver(this);
```

オブジェクトに注釈を付けて、必要なときに適切なメソッドを呼び出すように指示できます。

```java
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
void addLocationListener() { ... }
```

## ライフサイクル対応コンポーネントを作成する
このステップでは、アクティビティライフサイクルの所有者に反応するコンポーネントを作成します。フラグメントをライフサイクルの所有者として使用する場合、同様の原則と手順が適用されます。

Androidフレームワークの[*LocationManager*](https://developer.android.com/reference/android/location/LocationManager.html)を使用して、現在の緯度と経度を取得し、ユーザーに表示します。 この追加により、次のことが可能になります。

- 変更を講読し、LiveDataを使用してUIを自動的に更新します。
- アクティビティのステータスの変更に基づいて、登録および登録解除する[*LocationManager*](https://developer.android.com/reference/android/location/LocationManager.html)のラッパーを作成します。

通常、[*LocationManager*](https://developer.android.com/reference/android/location/LocationManager.html)をアクティビティの*onStart()*または*onResume()*メソッドの変更にサブスクライブし、*onStop()*または*onPause()*メソッドでリスナーを削除します。

```java
// Typical use, within an activity.

@Override
protected void onResume() {
    mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mListener);
}

@Override
protected void onPause() {
    mLocationManager.removeUpdates(mListener);
}
```

このステップでは、`BoundLocationManager`と呼ばれるクラスを更新してライフサイクルを認識します。`LifecycleOwner`の変更にバインド、監視、および対応します。
クラスがアクティビティのライフサイクルを監視するには、それをオブザーバとして追加する必要があります。これを実現するには、次のコードをコンストラクタに追加して、ライフサイクルを監視するように`BoundLocationManager`オブジェクトに指示します。

```java
lifecycleOwner.getLifecycle().addObserver(this);
```

ライフサイクルの変更が発生したときにメソッドを呼び出すには、`@OnLifecycleEvent`アノテーションを使用できます。`BoundLocationListener`クラスの次の注釈を使用して、`addLocationListener()`および`removeLocationListener()`メソッドを更新します。

```java
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
void addLocationListener() {
    ...
}
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
void removeLocationListener() {
    ...
}
```

> **注**：オブザーバーはプロバイダーの現在の状態に移行するため、コンストラクターから`addLocationListener()`を呼び出す必要はありません。 オブザーバーがライフサイクルの所有者に追加されたときに呼び出されます。

アプリを実行し、デバイスを回転させたときにログモニターに次のアクションが表示されることを確認します。

```console
D/BoundLocationMgr: Listener added
D/BoundLocationMgr: Listener removed
D/BoundLocationMgr: Listener added
D/BoundLocationMgr: Listener removed
```

Androidエミュレータを使用して、デバイスの場所の変更をシミュレートします（3つのドットをクリックして、拡張コントロールを表示します）。[*TextView*](https://developer.android.com/reference/android/widget/TextView.html)は、変更されると更新されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170755/4e76d6d4-43cd-7f81-b0e6-d56efe31cd22.png)

# 6.ステップ5-フラグメント間でViewModelを共有する
## フラグメント間でViewModelを共有する
[*ViewModel*](https://developer.android.com/reference/android/arch/lifecycle/ViewModel.html)を使用して次の追加手順を実行し、フラグメントと次の間の通信を有効にします。

- 単一のアクティビティ
- フラグメントの2つのインスタンス。それぞれに[*SeekBar*](https://developer.android.com/reference/android/widget/SeekBar.html)があります。
- [*LiveData*](https://developer.android.com/reference/android/arch/lifecycle/LiveData.html)フィールドを持つ単一の[*ViewModel*](https://developer.android.com/reference/android/arch/lifecycle/ViewModel.html)。

このステップを実行し（実行構成で「ステップ5」を選択）、互いに独立した[*SeekBar*](https://developer.android.com/reference/android/widget/SeekBar.html)の2つのインスタンスに注目してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170755/17fde23f-c7bb-8f68-fd72-21be72084242.png)
1つの[*SeekBar*](https://developer.android.com/reference/android/widget/SeekBar.html)が変更されたときに、他の[*SeekBar*](https://developer.android.com/reference/android/widget/SeekBar.html)が更新されるように、フラグメントを[*ViewModel*](https://developer.android.com/reference/android/arch/lifecycle/ViewModel.html)に接続します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170755/1d28efdf-dd86-dccb-11b3-30cdf5c672ac.png)

> **注**：各フラグメントのライフサイクルは独立しているため、アクティビティをライフサイクルの所有者として使用する必要があります。

この演習用のステップバイステップのマニュアルはありませんが、`step5_solution`パッケージで解決策を見つけることができます。

# 7.ステップ6-プロセスの再作成にわたってViewModelの状態を保持する（ベータ）
このセクションで使用されるモジュールは**ベータ段階**です。 これは、APIが将来変更される可能性があることを意味します。
メモリ管理の概要から：

> ユーザーがアプリを切り替えると、Androidはフォアグラウンドではない（つまり、ユーザーに表示されず、音楽再生などのフォアグラウンドサービスを実行していない）アプリを、最近使用されていない（LRU）キャッシュに保持します。たとえば、ユーザーが最初にアプリを起動すると、そのためのプロセスが作成されます。 しかし、ユーザーがアプリを離れると、そのプロセスは終了しません。システムはプロセスをキャッシュに保持します。ユーザーが後でアプリに戻ると、システムはプロセスを再利用するため、アプリの切り替えが速くなります。

システムのメモリが不足すると、キャッシュ内のプロセスのうち使用頻度が低いものから順に削除されます。ユーザーがアプリに戻ると、システムはアプリを新しいプロセスで再起動します。
これは、ユーザーがしばらくアプリと対話していない場合にのみ発生するため、アプリに戻って初期状態で見つけることは許可される場合があります。ただし、プロセスの終了時にその情報が失われないように、アプリまたはその一部の状態を保存したい場合があります。
`lifecycle-viewmodel-savedstate`モジュールは、ViewModelsに保存された状態へのアクセスを提供します。
このモジュールのgradle依存関係は

```gradle
"androidx.lifecycle:lifecycle-viewmodel-savedstate:$savedStateVersion"
```

依存関係を取得したら、デフォルトのフラグメントまたはアクティビティを使用している限り、*ViewModel*の*SavedStateHandle*にアクセスできます。[*SavedStateHandle*](https://developer.android.com/reference/androidx/lifecycle/SavedStateHandle)は、プロセスの終了後も存続するキーと値のマッピングです。
まず、これらの変更なしでステップ6を試してみましょう。

　1. 実行構成「ステップ6」を開きます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170755/85a31d1b-3e3e-f605-0f2e-e76001b61507.png)
簡単なフォームが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170755/d02e1007-53d0-ab88-8945-2554bf013d0a.png)

　2. 名前を変更して「保存」をクリックします。 これにより、*ViewModel*内の*LiveData*に保存されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170755/52ae7fab-3c08-568c-3be9-39ad664f45e6.png)

　3. プロセスを強制終了するシステムをシミュレートします（P +を実行するエミュレーターが必要です）。

まず、次のように入力してプロセスが実行されていることを確認します。

```console
$ adb shell ps -A |grep lifecycle
```

これにより、*com.example.android.codelabs.lifecycle*という名前の実行中のプロセスが出力されます。

デバイスまたはエミュレータで[ホーム]を押して、次を実行します。

```console
$ adb shell am kill com.example.android.codelabs.lifecycle
```

もう一度入力

```console
$ adb shell ps -A |grep lifecycle
```

何も得られないはずです。これはプロセスが正しく強制終了されたことを示します。

　4. アプリをもう一度開きます（アプリランチャーでLC Step6を探します）。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170755/b8654fc8-0b8b-8ff1-4a40-bcb81c295f14.png)

*ViewModel*の値は永続化されませんでしたが、`EditText`はその状態を復元しました。 これはどのように可能ですか？

> `EditText`を含む一部のUI要素は、独自の`onSaveInstanceState`実装を使用して状態を保存します。この状態は、プロセスが構成変更後に復元されたのと同じ方法で強制終了された後に復元されます。詳細については、[ViewModels: Persistence, onSaveInstanceState(), Restoring UI State and Loaders](https://medium.com/androiddevelopers/viewmodels-persistence-onsaveinstancestate-restoring-ui-state-and-loaders-fc7cc4a6c090)を参照してください。

実際、`lifecycle-viewmodel-savedstate`モジュールも`onSaveInstanceState`と`onRestoreInstanceState`を使用して*ViewModel*状態を永続化しますが、これらの操作はより便利になります。

## ViewModelの保存状態を実装する
`SavedStateViewModel.java`ファイルで、`SavedStateHandle`を取得してプライベートフィールドに状態を保存する新しいコンストラクターを追加する必要があります。

```java
private SavedStateHandle mState;

public SavedStateViewModel(SavedStateHandle savedStateHandle) {
   mState = savedStateHandle;
}
```

モジュールの*LiveData*サポートを使用して、*`ViewModel*に*LiveData*を保存および公開する必要がなくなりました。 既存のゲッターと`saveNewName`を次のように置き換えます。

```java
private static final String NAME_KEY = "name";

// Expose an immutable LiveData
LiveData<String> getName() {
    return mState.getLiveData(NAME_KEY);
}

void saveNewName(String newName) {
    mState.set(NAME_KEY, newName);
}
```

`mState`の*LiveData*を使用しているため、*MutableLiveData*名は使用されなくなり、削除できます。
これで、同じプロセスをもう一度試すことができます。 アプリを開き、名前を変更して保存します。次に、ホームを押して、プロセスを次のように強制終了します

```console
$ adb shell am kill com.example.android.codelabs.lifecycle
```

アプリを再度開くと、ViewModelの状態が今回保存されていることがわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170755/7a25c448-0362-c735-e423-84fa0a36a9e3.png)

[*SavedStateHandler*](https://developer.android.com/reference/androidx/lifecycle/SavedStateHandle.html)を使用すると、プリミティブ、バンドル、Parcelables、Serializablesおよびその他のタイプのデータを保存および復元できます。

詳細については、[*ViewModelドキュメントのSaved Stateモジュール*](https://developer.android.com/topic/libraries/architecture/viewmodel-savedstate)をご覧ください。