I’m having this really strange issue with compose ...
# compose-desktop
a
I’m having this really strange issue with compose for desktop. With the following code, sometimes the Text doesn’t update:
Copy code
import androidx.compose.material.Text
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.window.Window
import androidx.compose.ui.window.application
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlin.time.Duration.Companion.seconds

fun main() = application {
    Window(onCloseRequest = ::exitApplication) {
        var counter: Int by remember { mutableStateOf(0) }
        LaunchedEffect(Unit) {
            while(isActive) {
                delay(1.seconds)
                counter++
            }
        }
        Text(
            text = remember(counter) {
                counter.toString().also {
                    println("counter: $it")
                }
            },
        )
    }
}
Here’s a video to demonstrate what I mean. It will occasionally not update.
org.jetbrains.compose
version is 1.4.0
j
Not sure if the issue, but why having remember on counter inside Text? Its already remembered earlier in same composable?
a
I put the extra remember to print out
I’ll check without though
j
Could also try increment counter after its printed :)
a
it still happens occasionally with this:
Copy code
fun main() = application {
    Window(onCloseRequest = ::exitApplication) {
        var counter: Int by remember { mutableStateOf(0) }
        LaunchedEffect(Unit) {
            while (isActive) {
                delay(1.seconds)
                counter++
                println(counter)
            }
        }
        Text(
            text = counter.toString(),
        )
    }
}
I’ve checked with iOS and Android, this doesn’t happen 😕
j
And if doing println, counter++ and last delay in each loop? Feels like delay clock cycle different in desktop then causing compose skip frames as not fast enough, or cancels rendering as value changes before rendered
a
println, counter++, delay has the same effect
j
Then not sure, I guess coroutines in desktop causing other context switching compared.
a
Here is a slightly less trivial example that exhibits the same behaviour:
Copy code
import androidx.compose.material.Text
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.window.Window
import androidx.compose.ui.window.application
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.isActive
import kotlin.coroutines.coroutineContext
import kotlin.time.Duration.Companion.seconds

fun main() {
    val counterViewModel = CounterViewModel()
    application {
        Window(onCloseRequest = ::exitApplication) {
            val counter: String by counterViewModel.counter.collectAsState()
            Text(text = counter)
        }
    }
}

class CounterViewModel {
    val counter: StateFlow<String> = flow {
        var counter = 0
        while (coroutineContext.isActive) {
            emit(counter.toString())
            delay(1.seconds)
            counter++
        }
    }.stateIn(
        scope = GlobalScope,
        started = SharingStarted.WhileSubscribed(
            stopTimeoutMillis = 0,
            replayExpirationMillis = 0
        ),
        initialValue = "",
    )
}
I think it’s something related to text. Here is a fairly peculiar example (don’t judge me, it’s horrible I know 🙈 )
Copy code
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.material.Text
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.window.Window
import androidx.compose.ui.window.application
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlin.time.Duration.Companion.seconds

fun main() = application {
    Window(onCloseRequest = ::exitApplication) {
        var counterAndColor: Pair<String, Color> by remember { mutableStateOf("0" to 0.toColor()) }
        LaunchedEffect(Unit) {
            while (isActive) {
                delay(1.seconds)
                counterAndColor = counterAndColor.run {
                    val next = (first.toInt() + 1)
                    next.toString() to next.toColor()
                }
                println(counterAndColor)
            }
        }
        Box(modifier = Modifier.background(color = counterAndColor.second)) {
            Text(text = counterAndColor.first)
        }
    }
}

fun Int.toColor(): Color = if (this % 2 == 0) Color.Green else Color.Red
a
a
Thank you 😄
a
We’ll be releasing the next 1.4 update soon with the fix.
a
Great to hear! I was losing my mind over this for a day 😂
a
That’s nothing. I was losing my mind over it for a year.
a
your effort is greatly appreciated 😅
a
I believe I'm having this issue on Ubuntu now. @Alexander Maryanovsky Are there any estimates for the mentioned 1.4 update?
a
I noticed resizing the window "fixes" it 😅
a
We should be releasing a 1.4 update soon
Don’t have an exact date, unfortunately
Any redrawing fixes it
a
For me nothing fixes the issue, the text just doesn't update. However I see in the logs that recomposition does happen with the updated value.
Maybe I'm having a different issue...
a
It’s likely to be a different issue
a
Perhaps, the same issue on Android. I will check, thanks.
Ah, it appears that this is the same issue I have reported a few months ago: https://issuetracker.google.com/issues/270656235 Just in case anyone ever bumps into it. Basically
Text
is not updating sometimes, if placed inside
movableContentOf
.