Home > Mobile >  Why does Kotlin composable only update after for loop is over?
Why does Kotlin composable only update after for loop is over?

Time:03-20

I'm trying to update a composable using mutableState inside a loop, but it only updates to the last value, after the loop finishes:

In Main.kt

@Composable
fun App() {
    var myClass = remember { MyClass() }
    MaterialTheme {
        Column() {
            Text(text="${myClass.myInt.value}")
            Button(onClick = myClass::run){ Text(text = "RUN") }
        }
    }
}

where

class MyClass {
    val myInt = mutableStateOf(0)
    fun run(){
        for (i in 0..10){
            myInt.value = i
            Thread.sleep(500)
        }
    }
}

what am I missing? (I'm using Compose Desktop)

CodePudding user response:

Thread.sleep() pauses execution of your thread for the time given. Since you're calling it on the UI thread, it pauses all rendering and updating of any views in the whole app until it's done, so you'll never see any changes until the whole loop is done. Since it freezes the UI, it puts your app at risk of being shut down for not responding (ANR error).

You can do this using a coroutine and delay(), but you need to make it a suspend function. My apologies if there are any mistakes below, as I don't have any experience with Compose.

class MyClass {
    val myInt = mutableStateOf(0)
    suspend fun run(){
        for (i in 0..10){
            myInt.value = i
            delay(500)
        }
    }
}

// Main.kt:
@Composable
fun App() {
    var myClass = remember { MyClass() }
    val scope = rememberCoroutineScope()
    MaterialTheme {
        Column() {
            Text(text="${myClass.myInt.value}")
            Button(onClick = { scope.launch { myClass.run() }) { 
                Text(text = "RUN") 
            }
        }
    }
}
  • Related