
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