5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Lifecycle of composablesを読む

Last updated at Posted at 2023-06-09

前言

※AndroidのdevelopersサイトからUI architecture読んで、気になる部分をメモする感じです。

今回はlifecycleを拝見してます。
https://developer.android.com/jetpack/compose/lifecycle

キーワード

  • Composable@ComposableをつけてるClass、UIのパーツ
  • CompositionComposableから生成され、UIを記述するツリー構造
  • Compose:Jetpack Composeのシステムを指してる

メモ

Lifecycle overview

  • 唯一Compositionを変更する方法はrecomposition。

  • Composableのlifecycleはすごくシンプルで、以下の三つしかない。

    1. Compositionに入場
    2. recomposeしないか、recomposeする
    3. Compositionから退場
  • recompositionはState<T>の変更でトリガーされる。

Composableが複数回に呼ばれたときに、複数のインスタンスがCompositionに設置される。

@Composable
fun MyComposable() {
    Column {
        Text("Hello")
        Text("World")
    }
}

Anatomy of a composable in Composition

recompositionの時、Composableは呼ばれたかどうかで判断される。
もしComposableが前回のCompositionと今回も両方呼ばれた時はinputsが変わったかで判断される。

Add extra information to help smart recompositions

複数回Composableを呼ぶ場合は実行順序を識別子としてComposableを区別する。ただ、場合によって実行順序がうまく動作しない場合がある。

@Composable
fun MoviesScreen(movies: List<Movie>) {
    Column {
        for (movie in movies) {
            // MovieOverview composables are placed in Composition given its
            // index position in the for loop
            MovieOverview(movie)
        }
    }
}

こちらを例にすると、Listの最後に新しい項目を追加する時に、最後の項目以外の項目は同じ実行順序を使ってるため、recomposeしない。
ですが、Listの最前、途中に項目を追加すると、それ以外の項目も影響され、多数のComposableがrecomposeすることになる。

この場合は提供されてるkey()を使って、識別子を指定することができる。

@Composable
fun MoviesScreenWithKey(movies: List<Movie>) {
    Column {
        for (movie in movies) {
            key(movie.id) { // Unique ID for this movie
                MovieOverview(movie)
            }
        }
    }
}

また、lazyListにもDSLで提供してる

@Composable
fun MoviesScreenLazy(movies: List<Movie>) {
    LazyColumn {
        items(movies, key = { movie -> movie.id }) { movie ->
            MovieOverview(movie)
        }
    }
}

Skipping if the inputs haven't changed

もしComposableが既にCompositionにある場合、全てのinputsが安定してるなら、recomposeがスキップできる。

そして、以下の型は@Stableを明示しなくても、安定性があると扱われてる。

  • すべてのプリミティブ値型: Boolean、Int、Long、Float、Char など
  • 文字列
  • すべての関数型(ラムダ)

ただし、唯一可変型だけど安定性があるのがMutableState

またComposeが安定性を区別できない場合がある。例えばinterface、公開プロパティが可変として、仮に実装で不変の値を使っても安定してると扱いされない。その場合は@Stableを使ってComposeに指定できる。

// Marking the type as stable to favor skipping and smart recompositions.
@Stable
interface UiState<T : Result<T>> {
    val value: T?
    val exception: Throwable?

    val hasError: Boolean
        get() = exception != null
}

終わり

全然関係ないですけど、改行がうまく効かなくて、見にくいと改めて感じました。

5
1
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
5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?