Hey everyone! So I'm making a game for classes, I'...
# compose-desktop
d
Hey everyone! So I'm making a game for classes, I'm currently in a pretty advanced state, the last thing I'm lacking is a simple UI, as my whole project is in Kotlin, I thought that going with Compose was the best way to go... As I don't want to spend too much time on the UI (I want a simple grid to display my map and a sort of move-logger on the side), I tried to go with the following thing :
Copy code
@Composable
fun TileMatrixViewer(matrix: TileMatrix) {
    Text(Helper.displayer.showMap(matrix), fontFamily = FontFamily.Monospace)
}

object Helper {
    val displayer by lazy { BaseDisplayer() }
    /* some other things */
}
But the
Text
widget never updates when I change the position of a player, how can I make it so it is updated? You can see the whole class for
TileMatrix
right here on my git if it might help to answer -> https://github.com/HFDrae/RoguEngine/blob/main/src/main/kotlin/util/graph/tiles/TileMatrix.kt Another question that might make this one useless, how should I go if I want to display my grid as a grid of components rather than a String that represents the whole grid ? Thanks in advance !
d
Wrap your text in a
MutableStateFlow
set your text field's text to
yourStateflow.value
Copy code
<https://developer.android.com/jetpack/compose/state#state-in-composables>
This section is what you're looking for
d
Mmmhh... The text is not really changing as I change the content of the Matrix, I tried to wrap the
TileMatrix
in a
MutableStateFlow
(tried to modify in the
Stage
class) but it didn't work out... 😕 I also tried to do this :
Copy code
@Composable 
fun App() {
    val stage by remember {
        mutableStateOf(
            Helper.stageBuilder.setMatrixWidth(40).setMatrixLength(20).setRoomNumber(7).build()
        )
    }
    val map by remember { MutableStateFlow(stage.map) }


//    val player by Player(stage.map.)
    Helper.currentStage = stage

    Column(
        verticalArrangement = Arrangement.Center,
        modifier = Modifier.padding(5.dp)
    ) {
        Text(text)
        Text("-------------------")
        TileMatrixViewer(map.value)
    }
}
but the
val map by remember { ... }
cannot resolve (Error is :
Type 'TypeVariable(T)' has no method 'getValue(Nothing?, KProperty<*>)' and thus it cannot serve as a delegate
, but that's normal as
MutableStateFlow
does not take the
by
keyword)... Did I mess up to understand what I had to do? :#
c
I think your intuition of how Compose works with States is a bit off. Compose doesn’t just automatically watch for property changes and respond, it is specifically reading
State<T>
variables to know when to recompose. So any mutable variables (
var
,
MutableList
, etc.) are not going to automatically update the UI when they change, you need to use Compose features to let the runtime know when a change has happened. Instead, you need to use
mutableStateOf()
in place of `var`s,
mutableStateListOf()
in place of
mutableListOf()
, etc.
And the same idea goes for
StateFlow
. Simply wrapping a value in a
StateFlow
isn’t going to make it observable. You need your data itself to be immutable and contained within a StateFlow, so that the only way to change the data in it is to re-set the
.value
of the stateFlow. Once you’ve got that, you will need to collect it in Compose with
val map by stateFlow.collectAsState()
👍 1
d
So, if I understand correctly, I might need to retake things a bit to make it a more "compose-way"? For example in the case of my
TileMatrix
, I'll need to change in
Tile
the
var entity:Entity?
by
val entity by mutableStateOf<Entity?>(null)
and to wrap the
TileMatrix
in a
StateFlow
then in my
@Composable
do the
val map by matrixAsStateFlow.collectAsState()
?
c
Reactivity with Compose really needs to be built-in from the beginning, it’s difficult to take existing code with mutable structures and just “make it work” in Compose. I’d suggest getting your feet wet with Compose in general first and getting to understand how it works, before attempting to replace all the structures in your app (which might end up causing even bigger issues is you don’t really understand what’s going on under-the-hood). The official Compose Pathway is a great place to start
d
Reactivity with Compose really needs to be built-in from the beginning
Well... I won't have the time to retake everything for next week so I'll have to make it work somehow... x)
I'll take a look a better look at your link tomorrow morning, ty !
d
i have a list of items that i pull from the internet
i want my UI to stay updated with the most recent list
whenever i pull a new list, i call
items_.value = modRepoCache.items
to update the observable item list
in retrospect, i should be using
SnapshotStateList
via
mutableStateListOf
, also as Casey suggested. that way, i wouldn't need to replace the entire list each time
d
Thanks for your guidance @David W and @Casey Brooks, I managed to make it work as I wished thanks to you guys, know I might be able to get to the next step!