【Jetpack Compose】もう冗長なコードは不要! collectAsStateWithLifecycle で Flow を安全に収集する


Jetpack Compose の開発において、ViewModel が持つ StateFlow などの Flow を UI 側で購読して State として保持することはよくありますよね。

以前はライフサイクルを安全に考慮しようとすると LaunchedEffect や repeatOnLifecycle を組み合わせる必要がありましたが、現在は専用の拡張関数である collectAsStateWithLifecycle を使うことで、驚くほどシンプルに記述できるようになりました。

今回は、従来の書き方と新しくなったスマートな書き方を比較しながら、そのメリットを見ていきましょう!

 

🧑🏻‍💻 1. 従来の手法:LaunchedEffect + repeatOnLifecycle

まずは、ライフサイクルを安全に考慮して Flow を収集しようとした場合の従来のコードを見てみましょう。


@Composable
fun MyScreen(viewModel: MyViewModel = viewModel()) {
    val lifecycleOwner = LocalLifecycleOwner.current
    var state by remember { mutableStateOf<UiState>(UiState.Loading) }

    LaunchedEffect(viewModel.uiState, lifecycleOwner) {
        lifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
            viewModel.uiState.collect { value ->
                state = value
            }
        }
    }
}

・ ボイラープレートが多い: ライフサイクルの取得、LaunchedEffect の設定、repeatOnLifecycle のネストなど、記述量がどうしても多くなってしまいます。

・ 可読性の低下: 本来やりたいことは「StateFlow を Compose の State に変換すること」なのに、コードの大部分がライフサイクルの管理ボイラープレートになってしまいます。

 

🧑🏻‍💻 2. 新しい手法:collectAsStateWithLifecycle

AndroidX Lifecycle 2.6.0(および Compose Integration)以降では、このボイラープレートを丸ごと解決してくれる collectAsStateWithLifecycle() が提供されています。

先ほどのコードをこれに置き換えると、以下のようになります。


@Composable
fun MyScreen(viewModel: MyViewModel = viewModel()) {
    val uiState by viewModel.uiState.collectAsStateWithLifecycle()
}

たった 1行 です。

冗長だった LaunchedEffect や repeatOnLifecycle の記述が一切不要になり、コードが劇的にスッキリしました。

 

🧑🏻‍💻 3. collectAsStateWithLifecycle を使うべき理由

安全なライフサイクル管理
アプリがバックグラウンド(STARTED 状態を下回る時)に移行した際、自動的に Flow の収集を一時停止し、メモリやCPUリソースの無駄な消費を防ぎます。

コードの可読性と保守性向上
定型文(ボイラープレート)が消えるため、UI のロジックに集中しやすくなります。

公式が推奨するベストプラクティス
Jetpack Compose における標準的なデータ収集方法として公式ドキュメントでも推奨されています。

 

🧑🏻‍💻 まとめ

collectAsStateWithLifecycle を導入するだけで、安全性を担保しつつ、コードを圧倒的にクリーンに保つことができます。

まだ従来の LaunchedEffect や collectAsState() をそのまま使っている箇所があれば、ぜひこの機会に collectAsStateWithLifecycle() へ置き換えてみてください!


Related Categories :  Android・Developmemt・JetpackCompose・Kotlin・Newbie・Recommended