I have a method that runs some operations in a row. Is is actually a for loop, which loops it’s contents 50 times, each iteration taking roughly 0.2 seconds. I have a constant animation being presented on the screen for the duration of this execution. So, it is obvious that I wish to carry these operations off the main thread, so my animation can keep up (or the recompositions can take place, this is Compose). What I realized is, that this simple method
fun run(){
repeat(10000) {
repeat(5000){
print("I ♥ Kotlin")
}
}
}
if run in a standard Composable scope just like that, will block the UI thread as one would expect.
b) it would also block the UI thread if I call it in a LaunchedEffect while nesting it in a call to launch{...}.
c) It does not block if I run it on an I/O coroutine, which is also the default coroutine.
d) the app sometimes crashes if run on the Main Dispatcher
Now, simple question – why is this?
LaunchedEffect(Unit){
run() // Block
}
Launchedeffect(Unit){
launch{
run() // Block
}
}
LaunchedEffect(Unit){
withContext(Dispatchers.Main){
run() //Blocks, and at times, crashes
}
}
LaunchedEffect(Unit){
withContext(Dispatchers.IO){
run() // Runs without blocking
}
}
thread{
run() //Runs without blocking, no crash
}
Can anyone explain why the Dispatchers.IO works and the others don’t? It’s sort of giving me undesired stress.
If anyone requires a quick animation UI to test it out, here it is
@Composable
fun DUM_E_MARK_II() {
val sizeTransition = rememberInfiniteTransition()
val size by sizeTransition.animateFloat(
initialValue = 50f,
targetValue = 200f,
animationSpec = infiniteRepeatable(
keyframes { durationMillis = 1000 },
repeatMode = RepeatMode.Reverse,
)
)
Icon(
imageVector = Icons.Filled.Warning,
contentDescription = "",
modifier = Modifier.size(size.dp),
tint = Color.Red
)
}
>Solution :
Your code is a long-running, non-suspendable task. It blocks whatever thread it runs on for its entire lifetime. When you block the UI thread, it causes the UI to freeze, and after a timeout Android kills such a misbehaving application.
If you use any dispatcher that uses its own thread pool, for example IO, the task will block a non-UI thread.