従来、ActivityやFragmentのonResume()
やonPause()
に実装していた処理は、Lifecycle
を使ってComposable関数内に実装することができます。
やりたいこと
Jetpack ComposeでUIを構成しているアプリで、アプリがバックグラウンドに移行したりフォアグラウンドに移行したりした時に何らかの処理を行うため、従来のonResume()
やonPause()
に相当するイベントを取得します。
アプリ全体のonResume
やonPause
を検出したいのであれば、ルートのActivityにonResume()
やonPause()
を実装するという方法もあります。また、画面遷移をFragmentで実現している場合は、FragmentのonResume()
やonPause()
を使って、画面ごとに実装することもできます。しかし、Navigation Composeを使って一つのActivity・Fragment内で画面遷移を実現している場合に、特定の画面表示中にアプリがフォアグラウンド・バックグラウンドに移行したことを検出したい場合は、これらの方法は使えません。このような場合は、Lifecycle
を使います。
サンプル
ソースコードはGitHubにあります。
主な環境は以下の通りです。
- Kotlin 1.7210
- Compose Compiler 1.3.2
- Compose Libraries 1.2.1
- Material3 1.0.0-rc01
- Accompanist 0.25.1
ソースコード
実は、Lifecycleイベントを取得するサンプルコードは、Android Developerサイトに紹介されています。ただ、onResumeやonPauseなどのイベントを取得する方法として紹介されているのではなく、「クリーンアップが必要な作用」を実装するためのDisposableEffect()
の使用例として載っているので、探すのが難しいです。下記のソースコードは、Googleのサンプルコードを一部変更して使っています。
@Composable
fun ObserveLifecycleEvent(onEvent: (Lifecycle.Event) -> Unit = {}) {
// Safely update the current lambdas when a new one is provided
val currentOnEvent by rememberUpdatedState(onEvent)
val lifecycleOwner = LocalLifecycleOwner.current
// If `lifecycleOwner` changes, dispose and reset the effect
DisposableEffect(lifecycleOwner) {
// Create an observer that triggers our remembered callbacks
// for sending analytics events
val observer = LifecycleEventObserver { _, event ->
currentOnEvent(event)
}
// Add the observer to the lifecycle
lifecycleOwner.lifecycle.addObserver(observer)
// When the effect leaves the Composition, remove the observer
onDispose {
lifecycleOwner.lifecycle.removeObserver(observer)
}
}
}
ObserveLifecycleEvent()
は、イベントを監視する関数です。この関数は汎用的に使いまわしできます。
onEvent
引数は、イベント発生時に呼び出すコールバックです。rememberUpdateState()
でラップすることによって、ObserveLifecycleEvent()
が何度か再コンポーズされた場合でも、最新のonEvent
ラムダが使われるようになります。(そうしないと、DisposableEffect()
が実行された時点のonEvent
ラムダが残ってしまうのだと思います。)
LocalLifecycleOwner
を使うと、CompositionLocalの仕組みによって任意のコンポーザブル関数からLifecycleOwner
オブジェクトを取得できます。LifecycleOwner
クラスはlifecycle
プロパティ経由で、onResumeなどのイベントを監視できます。
DisposableEffect()
は、コンポーザブルに入場した時に処理を呼び出し、コンポーザブルから退場するときにonDispose
に記述した処理を呼び出すことができます。上の例では、コンポーザブルに入場する時にlifecycle.addObserver()
を呼び出してイベントの監視を開始し、退場するときにlifecycle.removeObserver()
を呼び出してイベントの監視を終了しています。また、DisposableEffect()
は引数のキー(上の例ではlifecycleOwner
)が変更されたときも、前回のonDispose
を呼び出したうえで新たな処理を呼び出します。ただ今回の例で、実際にlifecycleOwner
が変化するような場合があるのかどうかはよく分かりません。
LifecycleEventObserver
では、イベントを検出したら最新のonEvent
コールバックをcurrentOnEvent
オブジェクト経由で呼び出しています。
@Composable
fun LifecycleEventSample() {
Text(
text = "LifecycleEventSample",
)
ObserveLifecycleEvent { event ->
// 検出したイベントに応じた処理を実装する。
when (event) {
Lifecycle.Event.ON_RESUME -> Log.d("LifecycleEventSample", "On Resume")
Lifecycle.Event.ON_PAUSE -> Log.d("LifecycleEventSample", "On Pause")
else -> {}
}
}
}
次はObserveLifecycleEvent()
を使う側です。こちらは簡単です。コールバックに、検出したイベントに応じた処理を書いてあげればOKです。
イベントはLifecycle.Event
形式で渡されます。イベントの種類は、ON_CREATE
, ON_START
, ON_RESUME
, ON_PAUSE
, ON_STOP
, ON_DESTROY
の6種類があります。
注意点
コンポーザブルに入場し、初回にObserveLifecycleEvent()
を呼び出したとき、ON_CREATE
→ ON_START
→ ON_RESUME
の順にイベントが発生します。なんとなく、この関数を呼び出した時点でアプリが起動済みでActivityも起動済みであればON_CREATE
などのイベントは発生しないような気がしますが、実際には発生するので、余分な処理を実行してしまわないように注意が必要です。
また、コンポーザブルから退場するとき、ON_PAUSE
→ ON_STOP
→ ON_DESTROY
の一連のイベントが発生します。アプリが終了するわけではないので、こちらも必要な処理を停止してしまわないよう注意が必要です。
このような特徴があるので、ObserveLifecycleEvent()
は、画面全体を構成するコンポーザブル階層に実装するのが良いと思います。そうすることによって、ActivityのonResume
などのAPIと同じように、画面への出入りに関連したイベントを実装することができます。
コンテンツは随時追加していきます。