Compose LazyColumn:ListStateによる再Composeを回避

投稿日:  更新日:

ある成果物の開発を進めるに時に、「先に問題へ対応する」と「後で問題へ対応する」では、後者の方が難易度は高いです。

開発は進むにつれて周辺との因果関係が複雑化ます。全体に影響を与えない形で問題へ対応することが、難しくなるからです。

不要な再Composeを回避する対応も同じだと思います。

ですので、発生源が明確で不要な再Composeは、コーディングの段階で潰しておくべきです。

ただし、不要な再Composeの発生源を知らなければ出来ません。

ここで紹介するListStateは、不要な再Composeの発生源の一つです。

※環境:Android Studio Koala | 2024.1.1
    Kotlin 1.9.0
    Compose Compiler 1.5.1
    androidx.compose.foundation:foundation 1.6.8

スポンサーリンク

ListStateによる再Composeの発生

ListStateは一覧(リスト)表示の状態を保持しています。そして、スクロールを行うと、状態は時々刻々と変化します。

ですので、状態の読み出しを行った場合、スクロールで発生する状態の変化に合わせて再Composeがスケジュールされます。

以下は状態(LazyListState#firstVisibleItemIndex)に合わせて、ボタンを表示/非表示する例です。

@Composable
fun ListStateSample() {
    Box(modifier = Modifier.fillMaxSize()) {
        val _listState = rememberLazyListState()
        val _coroutineScope = rememberCoroutineScope()

        val _visible = _listState.firstVisibleItemIndex > 3    // true:表示、false:非表示

        LazyColumn(state = _listState) {
            items(24) {
                ItemBox { Text(text = "item %02d".format(it)) }
            }
        }

        AnimatedVisibility(		// ボタンの表示/非表示を切り替え
            modifier = Modifier.align(Alignment.BottomEnd).padding(10.dp),
            visible = _visible
        ) {
            Button(
                onClick = {
                    _coroutineScope.launch {
                        _listState.scrollToItem(index = 0)    // 一覧表示の先頭へジャンプ
                    }
                }
            ) { Text(text = "Top") }
        }
    }
}

この例は、一覧表示の先頭のアイテムが変わる毎に再Composeが発生します。

ListStateによる再Composeの発生

しかし、再Composeが必要なのはボタンの表示と非表示を切り替える時であって、その他は不要な再Composeです。

スポンサーリンク

再Composeを回避(derivedStateOfで分離)

derivedStateOf( )関数を利用すると、一覧表示の状態を持つListStateオブジェクトを、指定した計算式の結果を状態に持つオブジェクトに変換できます。

@StateFactoryMarker
fun <T> derivedStateOf(
    calculation: () -> T,			// 計算式
): State<T> = DerivedSnapshotState(calculation, null)

以下は、indexの変化の中から「index > 3」(指定した計算式の結果)になる変化を分離しています。これにより、必要な再Composeのみが行われます。

@Composable
fun ListStateSample() {
    Box(modifier = Modifier.fillMaxSize()) {
        val _listState = rememberLazyListState()
        val _coroutineScope = rememberCoroutineScope()

        val _visible = remember {
            derivedStateOf { _listState.firstVisibleItemIndex > 3 }
        }

        LazyColumn(state = _listState) {
            items(24) {
                ItemBox { Text(text = "item %02d".format(it)) }
            }
        }

        AnimatedVisibility(
            modifier = Modifier.align(Alignment.BottomEnd).padding(10.dp),
            visible = _visible.value
        ) {
            Button(
                onClick = {
                    _coroutineScope.launch {
                        _listState.scrollToItem(index = 0)
                    }
                }
            ) { Text(text = "Top") }
        }
    }
}

再Composeを回避(derivedStateOfによる分離)

スポンサーリンク

関連記事:

Jetpack composeは、アプリ開発に必要な一通りのUIコンポーネントをライブラリで提供しています。 そのライブラリ中のLazyColumnについて、構成や使用方法などをまとめます。 ※環境:Android Studio Koala | 2024.1.1     Kotlin 1.9.0     Compose Compiler 1.5.1     androidx.compose.foundation:foundation 1.6.8 ...
LazyColumnはLazyListScope DSLコマンドを使ってアイテムの並びを記述します。 コマンドは7つあり、各々について例を示します。 ※環境:Android Studio Koala | 2024.1.1     Kotlin 1.9.0     Compose Compiler 1.5.1     androidx.compose.foundation:foundation 1.6.8 ...
LazyColumnは「複数のデータやオブジェクト」または「コレクション」を一覧(リスト)表示するUIです。 単純に一覧表示できれば良い用途もありますが、表示に加えてアイテムの制御(変更/追加/移動/削除)を必要とする場面が多くあります。 最近の携帯端末はパソコンと同じ利便性をアプリに求めますから、「データの表示だけでなく編集もできる」という機能は必須の要望です。 ここでは、LazyColumnでアイテムの制御を行う方法を紹介します。 ※環境:Android Studio Koala | 2024.1.1     Kotlin 1.9.0     Compose Compiler 1.5.1     androidx.compose.foundation:foundation 1.6.8 ...
LazyColumnとColumnはどちらも一覧(リスト)表示するUIです。 記述方法は違いますが、スクロールしたり、アイテムを制御したり、ほぼ同じことが出来ます。 ただし、両者の特徴により、向き不向きがあります。よく違いを理解して、適材適所で使い分けが必要です。 ここでは、両者の違いをまとめました。 ※環境:Android Studio Koala | 2024.1.1     Kotlin 1.9.0     Compose Compiler 1.5.1     androidx.compose.foundation:foundation 1.6.8 ...
ある成果物の開発を進めるに時に、「先に問題へ対応する」と「後で問題へ対応する」では、後者の方が難易度は高いです。 開発は進むにつれて周辺との因果関係が複雑化ます。全体に影響を与えない形で問題へ対応することが、難しくなるからです。 不要な再Composeを回避する対応も同じだと思います。 ですので、発生源が明確で不要な再Composeは、コーディングの段階で潰しておくべきです。 ただし、不要な再Composeの発生源を知らなければ出来ません。 ここで紹介するList型入力は、不要な再Composeの発生源の一つです。 ※環境:Android Studio Koala | 2024.1.1     Kotlin 1.9.0     Compose Compiler 1.5.1     androidx.compose.foundation:foundation 1.6.8     kotlinx.collections.immutable 0.3.7 ...
Jetpack composeは、アプリ開発に必要な一通りのUIコンポーネントをライブラリで提供しています。 そのライブラリ中のLazyRowについて、構成や使用方法などをまとめます。 ※環境:Android Studio Koala | 2024.1.1 Patch 1     Kotlin 1.9.0     Compose Compiler 1.5.1     androidx.compose.foundation:foundation 1.6.8 ...
スポンサーリンク