Hello, I'm trying to update a composable using mu...
# compose-desktop
j
Hello, 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
Copy code
@Composable
fun App() {
    var myClass = remember { MyClass() }
    MaterialTheme {
        Column() {
            Text(text="${myClass.myInt.value}")
            Button(onClick = myClass::run){ Text(text = "RUN") }
        }
    }
}
where
Copy code
class MyClass {
    val myInt = mutableStateOf(0)
    fun run(){
        for (i in 0..10){
            myInt.value = i
            Thread.sleep(500)
        }
    }
}
what am I missing?
a
Your code is blocking. You can use one of the "Side-Effects API", e.g. produceState:
Copy code
val stateOfInt: State<Int> = produceState(0) {
    var result = withContext(<http://Dispatchers.IO|Dispatchers.IO>) {
        delay(1000)
        1
    }
    value = result

    result = withContext(<http://Dispatchers.IO|Dispatchers.IO>) {
        delay(1000)
        2
    }
    value = result
}
P.S. example above is "serial", second block will start when first one finish, to make it "parallel" wrap each block with "launch { }"
j
Does it mean I have to turn the run() function into a composable function?
I changed the code to a concrete example.
Someone solved the problem on StackOverflow, you just need to use a coroutine and delay. https://stackoverflow.com/questions/71542475/why-does-kotlin-composable-only-update-after-for-loop-is-over/71542756#71542756
a
produceState already has a coroutine
z
If you're running a loop with a delay to generate a stream of UI states, that sounds like an animation, in which case you should be using
withFrameMillis
instead of delay, if not one of the higher level apis.