基本的な実装と動作
以下のようなコードでは、アプリ(Activity)がpause中でもwhileループは自動的には停止しません。
LaunchedEffect(key1 = Unit) {
while (true) {
indicatorAlpha.floatValue = 1f
delay(1000L)
indicatorAlpha.floatValue = 0f
delay(1000L)
}
}なぜかというと、
- LaunchedEffectはComposable関数のライフサイクルに連動するが、Activityのライフサイクルとは直接連動しない
- whileループ内のdelayはsuspend関数だが、コルーチン自体は終了しない
- ActivityがonPause()に入ってもコルーチンは実行を継続する
という理由があるためです。
ライフサイクルに応じた制御の実装
Activityのpause中にループを停止するには以下のような実装が必要です。
var isRunning by remember { mutableStateOf(true) }
LaunchedEffect(isRunning) {
while (isRunning) {
indicatorAlpha.floatValue = 1f
delay(1000L)
indicatorAlpha.floatValue = 0f
delay(1000L)
}
}
DisposableEffect(key1 = LocalLifecycleOwner.current) {
val observer = LifecycleEventObserver { _, event ->
if (event == Lifecycle.Event.ON_PAUSE) {
isRunning = false
} else if (event == Lifecycle.Event.ON_RESUME) {
isRunning = true
}
}
LocalLifecycleOwner.current.lifecycle.addObserver(observer)
onDispose {
LocalLifecycleOwner.current.lifecycle.removeObserver(observer)
}
}Decomposeを使用したMultiplatformアプリでの実装
Decomposeを使用している場合は、Decomposeのライフサイクルを使用することができます。
class YourComponent(
componentContext: ComponentContext
) : ComponentContext by componentContext {
private val _isRunning = MutableValue(true)
val isRunning: Value<Boolean> = _isRunning
init {
lifecycle.doOnPause { _isRunning.value = false }
lifecycle.doOnResume { _isRunning.value = true }
}
}まとめ
Jetpack ComposeでLaunchedEffectとwhileループを使用する際は、ActivityやDecomposeのライフサイクルを使って適切なタイミングでループを停止・再開することができます。 これにより、アプリがバックグラウンドに移行した際に不要な処理が実行され続けることを防いでバッテリー消費を抑えることができます。 回しっぱなしのループを作らないように心がけましょう。