状態管理の基本:rememberとmutableStateOfの使い方【Jetpack Compose入門⑤】

状態管理とは?

Jetpack Composeにおける状態管理

Jetpack Composeでは、UIの再描画を最適化しながら動的なデータを扱うために「状態管理」が重要になります。状態(State)とは、UIの描画に影響を与えるデータのことです。例えば、ボタンのクリック回数やテキスト入力フィールドの内容などが状態に該当します。

Jetpack Composeでは、従来のAndroid開発におけるLiveDataViewModelとは異なり、よりシンプルな方法で状態を管理できます。その代表的な手段がremembermutableStateOfです。

rememberとmutableStateOfの基本

rememberとは?

rememberは、Jetpack Composeの再コンポーズ(再描画)が行われてもデータを保持するために使用されるComposable関数です。画面の状態を記憶し、値が保持されるため、例えばカウントアップするボタンなどの実装に使えます。

mutableStateOfとは?

mutableStateOfは、状態を管理するためのデータコンテナで、値の変更がUIに即座に反映される仕組みを提供します。Composeでは、このmutableStateOfrememberと組み合わせることで、状態を持続させます。

基本的な使い方

シンプルなカウンターアプリ

まずは、remembermutableStateOfを使ったシンプルなカウンターを実装してみましょう。

@Composable
fun CounterApp() {
    var count by remember { mutableStateOf(0) }

    Column(
        modifier = Modifier.padding(16.dp),
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Text(text = "カウント: $count", fontSize = 24.sp)
        Button(onClick = { count++ }) {
            Text(text = "増加")
        }
    }
}

コードの解説

  1. var count by remember { mutableStateOf(0) }
    • rememberを使ってmutableStateOf(0)をラップすることで、状態を保持します。
    • byを使うことで、count.valueではなくcountとして直接アクセス可能になります。
  2. Text(text = "カウント: $count", fontSize = 24.sp)
    • 現在のカウント数を表示します。
  3. Button(onClick = { count++ })
    • ボタンをクリックするとカウントが1増加します。
    • countの値が変わると、自動的にUIが再描画されます。

rememberとmutableStateOfの特性

再コンポーズの影響を受けない

rememberを使うことで、コンポーズの再実行時に変数がリセットされず、値が保持されます。

@Composable
fun Example() {
    var text by remember { mutableStateOf("初期値") }
    
    Column {
        Text(text = text)
        Button(onClick = { text = "変更された値" }) {
            Text("更新")
        }
    }
}

このコードでは、ボタンを押すとtextの値が変更され、即座に画面が更新されます。

rememberを使わない場合の問題点

もしrememberを使わなかった場合、コンポーネントが再コンポーズされるたびに変数が初期化されてしまいます。

@Composable
fun ExampleWithoutRemember() {
    var count = 0 // これではカウントが保持されない

    Column {
        Text(text = "カウント: $count")
        Button(onClick = { count++ }) {
            Text("増加")
        }
    }
}

このコードでは、ボタンをクリックしてもcountの値が保持されないため、カウントが増えません。

rememberとmutableStateOfの応用

テキスト入力フォーム

TextFieldを使ってユーザー入力を管理する場合も、remembermutableStateOfを活用できます。

@Composable
fun TextInputExample() {
    var text by remember { mutableStateOf("") }
    
    Column(modifier = Modifier.padding(16.dp)) {
        TextField(
            value = text,
            onValueChange = { text = it },
            label = { Text("入力してください") }
        )
        Text(text = "入力された内容: $text")
    }
}

このコードでは、TextFieldの入力値がリアルタイムで画面に反映されます。

ViewModelとの連携

より大規模なアプリでは、rememberだけでなくViewModelを使って状態を管理することが推奨されます。

class CounterViewModel : ViewModel() {
    var count by mutableStateOf(0)
        private set

    fun increment() {
        count++
    }
}

@Composable
fun CounterWithViewModel(viewModel: CounterViewModel = viewModel()) {
    Column(
        horizontalAlignment = Alignment.CenterHorizontally,
        modifier = Modifier.padding(16.dp)
    ) {
        Text(text = "カウント: ${viewModel.count}", fontSize = 24.sp)
        Button(onClick = { viewModel.increment() }) {
            Text(text = "増加")
        }
    }
}

この方法では、画面回転などで再生成されても、状態が維持されます。

まとめ

Jetpack Composeの状態管理において、remembermutableStateOfは基本的な仕組みです。

  • rememberは再コンポーズ時に状態を保持するために使用
  • mutableStateOfは変更可能な状態を作成し、UIをリアクティブに更新
  • rememberを適切に使わないと、再コンポーズ時に状態がリセットされる

さらに、アプリの規模が大きくなる場合は、ViewModelを活用するとより適切に状態を管理できます。ぜひ実際にコードを書いて試しながら、状態管理の理解を深めてください!