Kotlinそのものというより、Jetpack Compose において remember は「状態管理」を理解するうえで欠かせない存在です。
単なるユーティリティ関数ではなく、再コンポーズ(recomposition)というCompose特有の仕組みと密接に結びついたAPIです。
本記事では、
- なぜ
rememberが必要なのか rememberの基本的な役割- 再コンポーズとの正しい関係
mutableStateOfとの役割分担rememberSaveableとの違い- キー付き
remember - よくある誤解と注意点
という流れで、実務で使っても破綻しない理解を目指して解説します。
なぜ remember が必要なのか
Jetpack Composeは 宣言的UI を採用しています。
つまり、
「現在の状態がこうであれば、UIはこうなるべき」
という関係をコードで表現します。
この設計では、状態が変わるたびに Composable関数が再評価(再コンポーズ)される ことが前提になります。
再コンポーズで起きる問題
次のコードを見てください。
@Composable
fun Counter() {
var count = 0
Button(onClick = { count++ }) {
Text("$count")
}
}
このコードが期待通り動かない理由は、実は 2つ あります。
問題①:count は Compose の State ではない
count は単なるローカル変数なので、count++ しても Compose は変更を検知できません。
そのため、通常は 再コンポーズ自体が発生しません。
問題②:再コンポーズが起きた場合は必ず初期化される
仮に他のState変更などで再コンポーズが発生すると、Composable関数は再評価されるため、count は再び 0 に初期化されます。
再コンポーズをまたいで値を保持し、かつ変更をUIに反映させる仕組みが必要。
ここで remember が登場します。
remember の基本的な役割
remember の役割を一言でまとめると、
Composableが再評価されても、値を保持し続けるための仕組み
です。
基本形は次の通りです。
val value = remember { 初期化処理 }
この {} の中の処理は、
- 初回のコンポーズ時に評価される
- 再コンポーズ時には前回保持していた値が再利用される
という挙動になります。
再コンポーズと remember の正しい関係
Composeでは、Stateの変更などをきっかけに 再コンポーズが発生する可能性 があります。
重要なのは、
- 再コンポーズ = 必ず関数全体が毎回実行される
ではない、という点です。
Composeは最適化により、変更の影響がない部分の再評価を スキップ することがあります。
ただし概念的には、
- 再コンポーズでは 同じComposableが再評価される可能性がある
rememberはその再評価をまたいで値を保持する
と理解しておくと、実務上の齟齬は起きにくくなります。
remember と mutableStateOf の役割分担
この2つはセットで語られることが多いですが、役割は明確に異なります。
| API | 役割 |
|---|---|
remember | 値を再コンポーズ間で保持する |
mutableStateOf | 値の変更をComposeに通知し、再コンポーズを促す |
正しい組み合わせ例
@Composable
fun Counter() {
var count by remember { mutableStateOf(0) }
Button(onClick = { count++ }) {
Text("$count")
}
}
rememberによってcountの値は保持されるmutableStateOfによってcountの変更がStateとして監視される
この2つが揃って初めて、「状態として正しく振る舞うUI」になります。
remember が使える範囲と注意点
remember は Composable の中専用
fun foo() {
val x = remember { 10 } // ❌ コンパイルエラー
}
remember は Composableのライフサイクルに結びついたAPI のため、@Composable 関数の外では使用できません。
ViewModelの代替にはならない
remember で保持される値は、
- ComposableがCompositionに存在している間のみ有効
です。
そのため、
- 画面回転
- ナビゲーションで画面が破棄された場合
- プロセスキル
などでは 値は失われます。
画面やアプリ全体で共有・保持すべき状態は ViewModel を使います。
rememberSaveable との違い
rememberSaveable は remember の拡張版です。
挙動の違い
| API | 再コンポーズ | 画面回転 |
|---|---|---|
remember | 保持される | 失われる |
rememberSaveable | 保持される | 保持される |
var count by rememberSaveable { mutableStateOf(0) }
rememberSaveable は、
- プリミティブ型や
Parcelableなど - 「保存可能なUI状態」
を自動的に保存・復元します。
※ これは Composable内のUI状態向け の仕組みであり、ViewModelの SavedStateHandle とは用途・責務が異なります。
キー付き remember
remember にはキーを指定できます。
val user = remember(userId) {
loadUser(userId)
}
この場合、
userIdが同じ → 以前の値を再利用userIdが変わる → 初期化処理が再実行
という挙動になります。
依存関係のあるデータのキャッシュ に非常に有効です。
よくある誤解と注意点
誤解①:remember は永続的に保存される
❌ 永続ではありません
⭕ Composableのライフサイクル内のみ有効
誤解②:remember は状態管理の万能解
❌ 画面をまたぐ状態・ビジネスロジックには不向き
⭕ UIに近い一時的な状態向け
誤解③:remember は必ず mutableStateOf とセット
❌ 必ずではない
⭕ 重いオブジェクトの生成結果をキャッシュする用途でも使われる
(ただしライフサイクル理解が必須)
まとめ
最後に整理します。
| 状態の種類 | 適切な選択 |
|---|---|
| 一時的なUI状態 | remember |
| 回転でも保持したいUI状態 | rememberSaveable |
| 画面・ロジックをまたぐ状態 | ViewModel |
remember は「再コンポーズを安全に跨ぐための仕組み」であり、Composeの状態管理を成立させるための基礎です。
以上、Kotlinのrememberについてでした。
最後までお読みいただき、ありがとうございました。










