はじめに
Jetpack Composeでは、Composable内で状態を保持するためにrememberを使用することがあります。
しかし、画面回転などでActivityが再生成された場合、rememberで保持していた値は失われます。
そのような場合に利用されるのがrememberSaveableです。
rememberSaveableを使うことで画面回転後も状態を復元できますが、
-
rememberとの違いは何か - どのタイミングまで状態を保持できるのか
- アプリを強制終了した場合はどうなるのか
について、実際に検証して確認してみます。
動作確認環境
- Kotlin 2.4.0
- Jetpack Compose
- Material3
- Android Studio
検証アプリ
今回は以下のようなシンプルな検証画面を作成しました。
rememberとrememberSaveableそれぞれで、
- カウント値
- TextFieldの入力値
を保持します。
画面回転やアプリの強制停止後に、どのような違いがあるか確認します。
サンプルコード
今回作成した検証アプリのソースコードはGitHubで公開しています。
実装
rememberの場合
rememberを利用して状態を保持します。
var count by remember {
mutableIntStateOf(0)
}
var text by remember {
mutableStateOf("")
}
rememberSaveableの場合
rememberSaveableを利用して状態を保持します。
var count by rememberSaveable {
mutableIntStateOf(0)
}
var text by rememberSaveable {
mutableStateOf("")
}
今回の検証コードでは、同じUIに対して保持方法だけを変更し、挙動の違いを確認できるようにしています。
検証1:画面回転
まず、両方の項目に値を入力します。
その状態で端末を回転させます。
結果
| 状態保持方法 | 画面回転後 |
|---|---|
| remember | 状態が初期化される |
| rememberSaveable | 状態が復元される |
※比較しやすいように、結果確認時は縦向き表示に戻しています。
rememberの場合、画面回転によってActivityが再生成されるため、保持していた状態は失われました。
一方、rememberSaveableの場合は状態が復元されています。
なぜrememberSaveableは復元できるのか
rememberはComposition内で値を保持します。
そのためComposableがCompositionから破棄されると、保持していた状態も失われます。
一方、rememberSaveableは、Composable内の状態を保存可能な形式で管理し、
AndroidのActivity状態保存機構と連携します。
画面回転などでActivityが再生成される際に、保存された状態を取得して復元します。
状態保存の流れを簡単に表すと以下のようになります。
rememberSaveable
|
v
Composeの保存機構
|
v
Activityの状態保存機構
|
v
SavedInstanceState(Bundle)
|
v
Activity再生成時に復元
ただし、これは永続保存ではありません。
検証2:adbによる強制停止
次に、adbによる強制停止をした場合の挙動を確認します。
以下の手順でアプリを強制停止します。
- 値を入力した状態でアプリを起動したままにする
- adbコマンドを利用して強制終了する
- アプリを再度起動する
結果
| 状態保持方法 | adbによる強制停止後 |
|---|---|
| remember | 状態が初期化される |
| rememberSaveable | 状態が初期化される |
画面回転では復元できたrememberSaveableですが、今回はadb shell am force-stopによる強制停止を行ったため、Activityの状態保存情報が利用されず、rememberSaveableで保持していた状態も復元されませんでした。
rememberSaveableはActivityの状態保存機構を利用する仕組みであり、アプリの永続データを保存するものではありません。
rememberSaveableは永続保存ではない
今回の結果から、
| 状態保持方法 | 特徴 |
|---|---|
| remember | Compositionが存在する間だけ状態を保持する。Activity再生成では失われる |
| rememberSaveable | SavedStateを利用してActivity再生成後も復元できる。永続保存の仕組みではない |
という違いが分かります。
ユーザー設定やログイン情報など、アプリを終了しても保持したいデータはDataStoreやデータベースなど、別の永続化手段を利用する必要があります。
実際のアプリ開発での使い分け
rememberとrememberSaveableは、どちらを使うべきかではなく、どの期間データを保持したいかによって使い分けることが重要です。
例えば、以下のような基準で判断できます。
| 保持したいデータ | 適した方法 |
|---|---|
| Composable内だけで利用する一時的なUI状態 | remember |
| 画面回転後も維持したい入力値やUI状態 | rememberSaveable |
| アプリ終了後も保持したいユーザー設定 | DataStore |
| 大量データや構造化されたデータ | Roomなどのデータベース |
| 複数画面で共有する状態 | ViewModel + 保存機構 |
例えば、フォーム入力中の文字列や選択状態などは、画面回転によって失われるとユーザー体験を損なうため、rememberSaveableが適しています。
一方で、ログイン情報やユーザー設定など、アプリを再起動しても必要なデータはrememberSaveableではなく、永続化ストレージを利用する必要があります。
状態を保持する際は「どこまで復元したいのか」「そのデータの寿命はどの程度なのか」を考え、適切な保存方法を選択することが大切です。
まとめ
今回はrememberとrememberSaveableの違いを、実際に検証アプリを作成して確認しました。
結果をまとめると以下の通りです。
| 状態保持方法 | 再コンポーズ | Activity再生成 | adbによる強制停止後 |
|---|---|---|---|
| remember | ○ | × | × |
| rememberSaveable | ○ | ○ | × |
※今回の検証ではadbコマンドによる強制停止を行ったため、rememberSaveableも復元されませんでした。
ただし、OSによるメモリ解放目的のプロセス終了などではActivityの状態保存情報が利用される場合があり、復元される可能性があります。
rememberSaveableは画面回転などによるActivity再生成からUI状態を復元するための仕組みであり、永続保存の代替ではありません。
UI状態、一時的な入力状態、永続化が必要なデータなど、
保持したい期間に応じて適切な保存方法を選択することが重要だと分かりました。
実装時に意識したこと
今回の検証では、状態保持方法以外の条件を揃えるため、同じUIに対してrememberとrememberSaveableのみを変更しました。
比較対象以外の差分をなくすことで、それぞれの状態保持の違いを確認できるようにしています。




