LoginSignup
1
0

【Jetpack Compose】状態管理のためにremember、rememberSaveableの違いとSaverの活用

Posted at

Jetpack ComposeにおけるrememberrememberSaveable、そしてSaverの使用と、それらが状態管理にどのように役立つのかについて詳細に解説します。

rememberとは?

  • 目的: Composable関数内で状態を保持するために使用されます。

  • 特徴: rememberはコンポジションが破棄されるまで(例えば、Composable関数がナビゲーションによって画面から削除される、アクティビティが破棄されるなど)その状態を保持します。

  • 限界: アクティビティの再作成(デバイスの回転やバックグラウンドからの復帰など)では状態が保持されません。再作成時には初期化コードに戻ります。

rememberSaveableとは?

  • 目的: rememberと同様に状態を保持しますが、アクティビティの再作成を越えて状態を保持することができます。

  • 特徴: rememberSaveableは、システムによる再作成(デバイスの回転など)後も状態を復元するために内部的に保存されたインスタンス状態を使用します。

  • 用途: UIの状態(ユーザーの入力や選択など)をアクティビティの再作成を越えて保持したい場合に適しています。

  • カスタムクラスの保存: Saverインターフェイスを使用して、カスタムクラスや複雑な型の状態を保存・復元するロジックを定義します。

Saverとは?

  • 目的: rememberSaveableによるカスタムクラスの状態保存を可能にします。

  • 機能: カスタムクラスをシステムが理解できる形式(例: リストやマップ)に変換(シリアライズ)し、その後、これらの形式から元のカスタムクラスのインスタンスを復元(デシリアライズ)します。

  • 使用方法: rememberSaveablesaverパラメータにカスタムSaverのインスタンスを指定します。

状態管理の流れ

  1. 単純な状態(プリミティブ型など): rememberrememberSaveableを使用して状態を保持します。rememberは一時的な状態保持に、rememberSaveableは永続的な状態保持に適しています。

  2. カスタムクラスや複雑な状態: rememberSaveableとカスタムSaverを組み合わせて使用します。これにより、アクティビティの再作成を越えて状態を復元することが可能になります。

まとめ

Jetpack Composeにおける状態管理は、rememberrememberSaveableSaverを適切に使い分けることで、ユーザーインターフェイスの動的な挙動やアクティビティのライフサイクルを越えたデータの保持を効果的に実現できます。これらのツールを理解し、適切に使用することで、優れたユーザー体験を提供するアプリケーションを構築することができます。

コード例を用いたまとめ

@Composable
fun CraneEditableUserInput(
    hint: String,
    caption: String? = null,
    @DrawableRes vectorImageId: Int? = null,
    onInputChanged: (String) -> Unit
) {
    // Codelab: Encapsulate this state in a state holder
    var textState by remember { mutableStateOf(hint) }
    var isHint = true

    CraneBaseUserInput(
        caption = caption,
        tintIcon = { !isHint },
        showCaption = { !isHint },
        vectorImageId = vectorImageId
    ) {
        BasicTextField(
            value = textState,
            onValueChange = {
                textState = it
                if (!isHint) onInputChanged(textState)
            },
            textStyle = if (isHint) {
                captionTextStyle.copy(color = LocalContentColor.current)
            } else {
                MaterialTheme.typography.body1.copy(color = LocalContentColor.current)
            },
            cursorBrush = SolidColor(LocalContentColor.current)
        )
    }
}

例えば上記の関数があった時に、textStateに変更が入ると、CraneEditableUserInputは再実行されます。その時、ローカル変数であるisHintは初期値(true)に戻りますが、textStateはrememberなので初期値に戻りません。

画面が回転した時も同様の挙動になります。

次に、Activityが破棄された時、textStateはrememberなので破棄されます。状態を保持したい場合はrememberSaveableに変更する必要があります。

そして、rememberSaveableにカスタムクラスを入れたい時(ListやMapや複数の値を持つクラスなど)にSaverが登場します。

rememberSaveable(saver = CustomSaver) { ... }

のようにすると、カスタムクラスの保存が可能になります。

余談ですが、static変数(companion object内の変数など)はどこからでも参照可能なのに対して、rememberSaveableは定義されたComposable関数内でのみ使用可能です。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0