David Dupraz

06/23/2021, 1:25 PM
Hello, I have a problem in a card game project. I'm currently reworking some mechanisms to store the state in a normal class (without Composable methods) and make the GUI just watching this state. To synchronise both, I'm using some Composable callback. But for an unknown reason, the GUI does not recompose itself when state changes. It seems that notifications of the callbacks don't work, but I can't find why. Do you have an idea ? I put in a thread a link to a small reproducer and a video showing the issue.
Comment on the video: when the card is released (end of dragging), it should instantly appear in the central row. But the card stays where it is: central row is not recomposed. A reproducer of the issue is available here

Igor Demin

06/23/2021, 1:36 PM
Instead of using callbacks in your state you can use mutableStateOf directly: instead of
. Composable that uses this state should be recomposed automatically, no need in callbacks.
I misread the code 🙂 . If you use
in your state instead of that, Composable will be recomposed automatically.
But if you want to continue to use callbacks, you should change returning type to State, so an upper-level Composable will be subscribed to it:
fun getPlayerRowCards(game: Game): State<MutableList<PlayCard>>{
    var cards = remember { mutableStateOf(game.playerRowCards) }
    DisposableEffect(game) {
        val callback =
            object : GameCallback {
                override fun onNewCard() {
        onDispose { game.unregisterToPlayerRow(callback) }
    return cards

David Dupraz

06/23/2021, 2:56 PM
Thanks four your answer. Both solutions work... in the reproducer. In the big project, program freezes after calling to callback or accessing the list 😕

Michael Paus

06/24/2021, 7:24 AM
I had the same issue some time ago. In my case the problem was that the exported state was never actually used inside the composable wrapper function and therefore the background magic did not see a reason to recompose (or redraw). So I introduced an empty function which consumed the state and that did the trick to force a redraw.