【Android】Composeの基本

Composeの基本についてまとめます。

開発者

Jetpack Compose = Google

Compose Multiplatform = Kotlin開発元のJetbrains

宣言的UIについて

今までの命令的UIではデータを修正した後に更新メソッドなどを呼ぶ必要がありますが、宣言的UIでは更新メソッドを呼ばなくてもレイアウトが勝手に更新されます。

宣言的UIでは「How(どのように処理をさせるか)」のみを記述する

従来のXMLレイアウトのデメリット

  • XMLレイアウトファイルが増える
  • コンポーネント化する際に手間がかかる(データバインディング等)

Composeのメリット

  • コードの行数が削減できる(RecyclerViewが不要)
  • XMLレイアウトのファイルが不要になる

Composableのルール

コンポーザブル関数の名前は先頭が大文字の名詞として命名することが推奨されている。

またコンポーザブル関数の呼び出しはコンポーザブル関数内かsetContentメソッドのエントリーポイントからでしかしか呼び出すことができない

状態管理

状態の保持の仕方としてはコンポーザブル内で変数を保持して管理する

    Kotlin
    @Composable
    fun switchSample {
      var checked by remember { mutableStateOf(false) }
      Switch(checked = checked, onCheckChanged = { checked = !checked })
    }

    関数内で定義している変数をSwitchと同期させることでcheckedが更新された時にレイアウトも自動で更新される。

    mutableStateOfでの変更をCompose Runtimeが通知をフックし、rememberを利用することで同じツリーのUI上での変更がある場合にそのUIのmutableStateを返してくれる。byはシンプルにswiftでいうget { mutableStateOf(false) }みたいな書き方

    Switch自体がisCheckedのようなプロパティを保持はしておらず外部から状態を渡して同期させる!

    Compose Runtimeによる再コンポーズの流れ

    1. Composableを実行
    2. Compose RuntimeがStateの値(状態)を記録する
    3. Stateの値が変更される
    4. 変更通知を受け取り、記録していた該当するComposableを無効化
    5. そのComposableだけ再実行する

    mutableStateOfを利用していてrememberを利用しない場合は再コンポーズは発生するが、値は初期値に戻る。そのためrememberを利用すると同じインスタンスを再利用するため変更されたComposableが保持している変更された値が利用される。

    Composeが生きている期間について

    画面遷移などでComposableがComposition(表示過程+UI記録)から削除された場合にStateも死ぬ

    Navigationのbackstackにあり、表示されていないがCompositionに残っている場合はrememberに保持される。

    もし画面遷移後も保持したい場合はrememberSaveableかViewModel or State hoistingで保持させる

    UIの階層構造からComposableを分割する

    1つのComposableに全て書こうとすると可読性が悪くなるし、変更が必要ない箇所まで再コンポーズされてしまうことになるので小分けにする。

    手書きでいいのでUIの階層構造を可視化して、リストのように重複するようなコードはComposableに分けて親Composableはよりシンプルにする。

    データを上位の階層に渡す

    下位の階層に渡すにはComposable関数にパラメータとして渡すだけでしたが、上位に渡す場合は共通の親階層に状態を定義します。

    その場合はクロージャを利用して変更を上位に伝えます。

    この場合の注意点としてStateを利用しているComposableが再コンポーズされると、子に該当するComposableも再コンポーズされる