What's the difference between LaunchedEffect and Composable function? Except coroutine scope in launch effect
val currentProgress = GlobalLoader.current
LaunchedEffect(progress) {
progress ?: return@LaunchedEffect
onProgressCatch()
currentProgress.showIf(progress)
}
@Composable
private fun ListenProgress(
progress: Boolean?,
onProgressCatch: VoidCallback,
) {
progress ?: return
onProgressCatch()
GlobalLoader.current.showIf(progress)
}
When a Composable enters composition LaunchedEffect() gets triggered. If LaunchedEffect has key or keys it can be triggered on recompositions when key values change.
It provides a coroutineScope that can be used with animations.
And one time actions that supposed to happen when a condition is true
val currentProgress = GlobalLoader.current
LaunchedEffect(progress) {
progress ?: return@LaunchedEffect
onProgressCatch()
currentProgress.showIf(progress)
}
this one only triggers when your Composable enters recomposition and when progress value changes. And since you check for nullability it only gets invoked when null till progress ?: return@LaunchedEffect
when not null rest of the code is invoked.
@Composable
private fun ListenProgress(
progress: Boolean?,
onProgressCatch: VoidCallback,
) {
progress ?: return
onProgressCatch()
GlobalLoader.current.showIf(progress)
}
Is invoked every time recomposition happens. If your progress is not null it will be called several times if you run an animation for instance that could trigger recomposition on every frame your callback will also be invoked
You can check out other question about LaunchedEffect for more detail
How can I launch a function only onetime when I use Jetpack Compose?
Use of LaunchedEffect vs SideEffect in jetpack compose
Let's consider 2 versions of a function as in question.
@Composable
private fun ListenProgress2(
progress: Boolean?,
onProgressCatch: () -> Unit,
) {
progress ?: return
println("🚙 ListenProgress()2")
LaunchedEffect(key1 = progress){
println("🍎 ListenProgress()2")
onProgressCatch()
}
}
@Composable
private fun ListenProgress(
progress: Boolean?,
onProgressCatch: () -> Unit,
) {
progress ?: return
println("🚀 ListenProgress()1")
onProgressCatch()
}
And they are called in parent as
@Composable
private fun Sample() {
var value by remember { mutableStateOf(0f) }
Slider(value = value, onValueChange = { value = it }, valueRange = 0f..100f)
val progress: Boolean? = if (value > 5) true else null
ListenProgress(progress = progress) {
println("😜 Hello World $value")
}
ListenProgress2(progress){
println("🍏 Hello World2 $value")
}
}
If slider is moved in logs you will see something similar
🚀 ListenProgress()1
I 😜 Hello World 5.4463773
I 🚙 ListenProgress()2
I 🍎 ListenProgress()2
I 🍏 Hello World2 5.4463773
I 🚀 ListenProgress()1
I 😜 Hello World 6.5251245
I 🚀 ListenProgress()1
I 😜 Hello World 7.3171854
I 🚀 ListenProgress()1
I 😜 Hello World 8.200772
I 🚀 ListenProgress()1
I 😜 Hello World 9.236124
I 🚀 ListenProgress()1
I 😜 Hello World 9.781246
I 🚀 ListenProgress()1
I 😜 Hello World 10.948928
I 🚀 ListenProgress()1
I 😜 Hello World 11.660738
I 🚀 ListenProgress()1
I 😜 Hello World 13.263601
I 🚀 ListenProgress()1
I 😜 Hello World 14.22418
I 🚀 ListenProgress()1
I 😜 Hello World 15.987328
I 🚀 ListenProgress()1
I 😜 Hello World 16.761938
I 🚀 ListenProgress()1
I 😜 Hello World 18.055727
I 🚀 ListenProgress()1
I 😜 Hello World 18.598866
I 🚀 ListenProgress()1
I 😜 Hello World 19.164701