LaunchedEffect
LaunchEffect allows us to use coroutines in Composable
@Composable fun DisposableEffect(
vararg keys: Any?,
effect: DisposableEffectScope.() -> DisposableEffectResult
): Unit
- Like the
DisposableEffect
same,Composable
execute block when entering composition - When Composable is detached from the tree, CoroutineScope executes cancel
- If the parameter keys change, it will be executed
cancel
again after executioneffect
In short, it supports the execution of Coroutine's DisposableEffect, which will automatically execute cancel without manualonDispose
Instructions
The usage is as follows:
@Composable
fun SplashScreen(
onTimeOut: () -> Unit
) {
LaunchedEffect(Unit) {
delay(SplashWaitTime)
onTimeOut()
}
...
}
For example, above, the screen opening page is displayed at the first startup. Parameter Unit, because there will be no diff, the life cycle effect of onActive is realized, that is, it is executed once at the first composition
@Composable
fun SearchScreen() {
...
var searchQuery by remember {
mutableStateOf("") }
LaunchedEffect(searchQuery) {
// execute search and receive result
}
...
}
As above, when the search term changes, the search is initiated.
The important significance of letting Composable support coroutines is that some simple business logic can be directly encapsulated and reused in the form of Composable without the need for additional ViewModel.
Realization principle
@Composable
@ComposableContract(restartable = false)
fun LaunchedEffect(
subject: Any?,
block: suspend CoroutineScope.() -> Unit
) {
val applyContext = currentComposer.applyCoroutineContext
remember(subject) {
LaunchedEffectImpl(applyContext, block) }
}
The implementation is very simple, use the remember
saved subject parameter, and then LaunchedEffectImpl
start the coroutine
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
}
}
LaunchedEffectImpl
It can be provided CoroutineScope
, with the help of the CompositionLifecycleObserver
provided life cycle, the launch
coroutine is started when entering the screen, and the coroutine is cancel
cancelled when leaving the screen .