Maybe I missed something completly obvious but I t...
# compose-desktop
t
Maybe I missed something completly obvious but I tried to create an lazy list from the return of a flow but the State dosn't get updated Code in the 🧵 [SOLVED]
Copy code
data class RowData(
    val data1: Int,
    val data2: String,
    val data3: Double,
    val data4: Int,
    val data5: Double,
)

fun main() {
    val fetchData = flow<List<RowData>> {
        val ret = mutableListOf<RowData>()
        for (n in 0 until 20) {
            ret.add(RowData(n, "Hi", n.toDouble(), n, n.toDouble()))
            emit(ret)
            delay(50)
        }
    }

    Window("Test", IntSize(600, 400)) {
        MaterialTheme {
            val rowList by fetchData.collectAsState(listOf())
            println("recomposed")

            val state = LazyListState(0, 0)
            LazyRow(state = state, modifier = Modifier.fillMaxSize()) {
                items(rowList) {
                    Row(
                        horizontalArrangement = Arrangement.SpaceAround,
                        verticalAlignment = Alignment.CenterVertically,
                        modifier = Modifier.fillParentMaxWidth(),
                    ) {
                        Text(it.data1.toString())
                        Text(it.data2)
                        Text(it.data3.toString())
                        Text(it.data4.toString())
                    }
                }
            }
        }
    }
}
Setup versions:
Copy code
plugins {
    kotlin("jvm") version "1.4.32"
    id("org.jetbrains.compose") version "0.4.0-build180"
}
z
You’re repeatedly emitting the same list instance, and mutable state doesn’t notify changes if the same value is set multiple consecutive times. In general, you don’t want to emit mutable values in a flow, or store them in a mutable state.
Change your list to be an immutable one, emit a new instance on every iteration.
t
doesn’t notify changes if the same value is set multiple consecutive times.
I thought the hashcode has to be diffrent? I now also tried it out with an Object and in my testings it only worked with 'primitiv' types (tested with List, Array, DataObject, Int and String)
t
You could instead of using flow use a
Copy code
mutableStateListOf<>()
which will keep track of changes.
t
Copy code
fun main() {
    val itemList = mutableStateListOf<RowData>()
    val fetchData = flow<Unit> {
        for (n in 0 until 20) {
            val toAdd = RowData(n, "Hi", n.toDouble(), n, n.toDouble())
            itemList.add(toAdd)
            delay(50)
        }
    }

    Window("Test", IntSize(600, 400)) {
        MaterialTheme {
            println("recomposed")

            LaunchedEffect(Unit) {
                fetchData.collect()
            }

            val state = LazyListState(0, 0)
            LazyRow(state = state, modifier = Modifier.fillMaxSize()) {
                items(itemList) {
                    Row(
                        horizontalArrangement = Arrangement.SpaceAround,
                        verticalAlignment = Alignment.CenterVertically,
                        modifier = Modifier.fillParentMaxWidth(),
                    ) {
                        Text(it.data1.toString())
                        Text(it.data2)
                        Text(it.data3.toString())
                        Text(it.data4.toString())
                    }
                }
            }
        }
    }
}
Doesn't work either 😬 Even if I make it inline wihout using a flow to dispatch the updates
Copy code
fun main() {
    Window("Test", IntSize(600, 400)) {
        MaterialTheme {
            println("recomposed")

            val itemList = mutableStateListOf<RowData>()
            LaunchedEffect(Unit) {
                for (n in 0 until 20) {
                    val toAdd = RowData(n, "Hi", n.toDouble(), n, n.toDouble())
                    itemList.add(toAdd)
                    delay(50)
                }
            }

            val state = LazyListState(0, 0)
            LazyRow(state = state, modifier = Modifier.fillMaxSize()) {
                items(itemList) {
                    Row(
                        horizontalArrangement = Arrangement.SpaceAround,
                        verticalAlignment = Alignment.CenterVertically,
                        modifier = Modifier.fillParentMaxWidth(),
                    ) {
                        Text(it.data1.toString())
                        Text(it.data2)
                        Text(it.data3.toString())
                        Text(it.data4.toString())
                    }
                }
            }
        }
    }
}
t
Can you try to fetch the items using
Copy code
LaunchedEffect(..) {
   withContext(<http://Dispatchers.IO|Dispatchers.IO>) {
      ....
   }
}
Oh yes sorry
did not read the complete source
t
I do. Nothing changed by using another Dispatcher
t
It should work. I used it this way many times.
Just a second i will test.
t
strange 🤔
Got it 🤦‍♀️ LazyRow -> LazyColumn
1
t
But it work also with LazyRow but you have to scroll 😄
And in Compose for Desktop scrolling does not work out of the box 😞
🚫 1
t
Yes because of 😂
Modifier.fillParentMaxWidth()
It sure does Ctrl + Scroll Wheel 👍
t
Ok yes i see.
If you want to use flow for emitting elements in Android Compose you could use pageing library for this. And emit single items not the complete list. But in Desktop Compose there is no solution out of the box
I wrote some helper to do it. But not really released a library for this yet.
t
nice to know thanks 👍 But I try to stay multiplattform as good as possible with my application The goal was to do a list that shows the item as fast as it got loaded
👍 1