【Jetpack Compose/Android】LifeCycleのイベント取得と監視!
この記事からわかること
- Kotlin/Android Jetpack ComposeのLifeCycleとは?
- ライフサイクルイベントの監視と取得方法
index
[open]
\ アプリをリリースしました /
環境
- Android Studio:Meerkat
- Kotlin:2.0.21
- Material3
- AGP:8.9.2
- Gradle:8.11.1
- Mac M1:Sequoia 15.4
Jetpack Compose自体の基本的な使用方法に関しては以下の記事を参考にしてください。
Composable関数とは
公式リファレンス:Lifecycle of composables
Jetpack ComposeではUIを構築するための関数に@Composableアノテーションを付与する設計になっておりこれを「Composable関数」と呼びます。Composable関数では従来のXMLベースのUI構築とは大きく異なり、宣言的にUIを記述できるようになっています。
Composable関数は状態(State)に基づいてUIが描画されます。TextFieldなどがイメージがつきやすいと思いますが、テキスト入力欄の文字列(=状態)の変化イベントを駆動としてComposableが自動的に再コンポーズする流れ(Recomposition)になっています。そして再描画対象となるのはその状態を参照しているUIのみになります。
これまでのActivityやFragmentのライフサイクルとは大きく異なるのがComposable関数の大きな特徴です。
Composableのライフサイクル
Composableのライフサイクルを理解するためにはCompositionという概念の理解が重要です。CompositionとはComposable関数を実行してUIツリーを構築するプロセスのことです。つまり実際にUIが描画されるためのプロセスになり、それをComposable関数が「Compositionに入る」と言ったりします。その後「0回以上再コンポーズ(Recomposition)」され、「Compositionから出る(Disposal)」という一連のイベントで定義されています。
- Composition:UIツリーを構築するプロセス。ComposableがUIツリーに「初めて」入る際に生成
- Recomposition:監視している状態(State<T> など)の変化に応じて「必要な部分だけ」再描画
- Disposal:ComposableがCompositionから外れる。そのStateも破棄される
LaunchedEffect
Compositionの変化に紐づく形で使用できるのがLaunchedEffectです。引数にLaunchedEffectを識別するためのキーと実行したい処理をsuspend関数で受け取ります。
@Composable
@NonRestartableComposable
@Suppress("ArrayReturn")
@OptIn(InternalComposeApi::class)
fun LaunchedEffect(
vararg keys: Any?,
block: suspend CoroutineScope.() -> Unit
) {
val applyContext = currentComposer.applyCoroutineContext
remember(*keys) { LaunchedEffectImpl(applyContext, block) }
}
LaunchedEffectはComposable関数がCompositionに入ったときにコルーチンを起動します。Compositionから外れると起動していたコルーチンも自動的にキャンセルされ、異なるキーで呼び出すと前のコルーチンはキャンセルされ、新しいコルーチンが起動します。
@Composable
fun UserScreen(vm: UserVm = hiltViewModel()) {
// Composable関数がCompositionに入ったときにコルーチンを起動
// キーにUnitを指定すると入場時に一度だけコルーチンを起動させることができる
LaunchedEffect(Unit) {
// この中ではsuspend関数を呼べる
vm.load()
}
DisposableEffect(Unit) {
vm.startListen()
onDispose { vm.stopListen() }
}
}
DisposableEffect
軽く先出ししましたがDisposableEffectはComposable関数がCompositionに入ったときと、Compositionから出たときに実行したい処理をコルーチンに含めて起動します。Compositionから外れたタイミングでonDispose内に定義した処理が実行されます。異なるキーで呼び出されると前のonDisposeが実行され、新しいコルーチンが起動します。
@Composable
fun UserScreen(vm: UserVm = hiltViewModel()) {
// Composable関数がCompositionから出たときにコルーチンを起動
DisposableEffect(Unit) {
// リソースの登録・解放に最適
vm.startListen()
onDispose { vm.stopListen() }
}
}
SideEffect
SideEffectはComposable関数が再コンポーズ(Recomposition)が終わった直後にコルーチンを起動します。Recompositionが発生するたびに実行されるので状態更新やUI再構築が完了した後に実行したい処理を記載するのに最適です。
@Composable
fun Counter() {
var count by remember { mutableStateOf(0) }
Button(onClick = { count++ }) {
Text("Clicked $count times")
}
SideEffect {
// Recomposition が完了するたびに呼ばれる
println("SideEffect: count=$count")
}
}
定義を確認するとわかりますが、SideEffectはsuspend関数は呼び出せないので注意してください。
@Composable
@NonRestartableComposable
@OptIn(InternalComposeApi::class)
fun SideEffect(
effect: () -> Unit
) {
currentComposer.recordSideEffect(effect)
}
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。







