Jetpack Compose で開発する上できっと使うことになるであろう LaunchedEffect
についてみていこうと思います。
※この記事は Jetpack Compose 1.0.0-alpha09 時点の内容のため、stable までに大きく変わる可能性があります
LaunchedEffect
とは
- Composable がコンポジションに入る時に実行される関数
- コンポジションを離れる時に実行している処理をキャンセル
- 引数の subject が変更された時にも実行している処理をキャンセルして再度実行
- 実行する処理は
CoroutinesScope
で行われる
箇条書きすると上記のことを行う関数で、Composable が表示されるタイミングに何か処理を実行したい時に使用します。
LaunchedEffect
の使い方
ただ Composable が表示されるタイミングだけ処理をしたい場合は以下のように subject に Unit を指定します。
@Composable
fun SplashScreen(
onTimeOut: () -> Unit
) {
LaunchedEffect(Unit) {
delay(SplashWaitTime)
onTimeOut()
}
...
}
subject に値を渡す場合だと、例えば検索時のサジェストの処理に使えたりします。
@Composable
fun SearchScreen() {
...
var searchQuery by remember { mutableStateOf("") }
LaunchedEffect(searchQuery) {
// execute search and receive result
}
...
}
LaunchedEffect
の実装を覗いてみる
LaunchedEffect
のコードをみると subject を remember で保存し、変更があれば処理を再実行するようになっています。
@Composable
@ComposableContract(restartable = false)
fun LaunchedEffect(
subject: Any?,
block: suspend CoroutineScope.() -> Unit
) {
val applyContext = currentComposer.applyCoroutineContext
remember(subject) { LaunchedEffectImpl(applyContext, block) }
}
LaunchedEffectImpl
の方では Composable のライフサイクルを扱う CompositionLifecycleObserver
でコンポジションに入った時に処理の実行、離れた時で Job
のキャンセルを行っています。
internal class LaunchedEffectImpl(
parentCoroutineContext: CoroutineContext,
private val task: suspend CoroutineScope.() -> Unit
) : CompositionLifecycleObserver {
private val scope = CoroutineScope(parentCoroutineContext)
private var job: Job? = null
override fun onEnter() {
job?.cancel("Old job was still running!")
job = scope.launch(block = task)
}
override fun onLeave() {
job?.cancel()
job = null
}
}