This is going to sound very obvious, but I've alwa...
# compose
c
This is going to sound very obvious, but I've always struggled with
collectAsState
… Assuming a function
Copy code
fun foo(id: Int) = flow {
    expensiveNetworkRequest(id)
}.flowOn(<http://Dispatchers.IO|Dispatchers.IO>)
What is the correct way to collect it as state?
Copy code
@Composable
fun Foo(id: Int) {
    // BAD: a new flow is created on each composition, leading to a recomposition loop
    val result1 by foo(id).collectAsState()

    // BAD: seems to also create a recomposition loop
    val result2 by remember(id) { foo(id) }.collectAsState()

    // GOOD?
    val result3 by remember(id) { foo(id).collectAsState() }

    Text(resultX)
}
c
Is there a reason you need to call foo in this Composable? Why not put it in a VM and pass the state in?
c
ViewModel is Android-only, right?
c
Android has a ViewModel class yes, but the concept applies generally
c
How would you write this example in a multiplatform way?
m
Copy code
result2
should be fine. What you say is a ‘recomposition loop’ is probably recomposition due to state emission
just log the function and check only one call per id
you are remembering the flow as long as it is the same id - and transforming the flow to a State<V>. It is perfectly fine i think
if the id changes, you want to collect from the new flow. so remember will call the function again and re-collect
from what i understand of your code, thats exactly what you need
c
That's indeed what I want, but last time I tried it looped infinitely 🤔
m
if you are using ‘result2’, it can only loop ‘indefinitely’ if the key changes indefinitely
c
I'll try again and check how it works. Thanks
m
if you want to make sure, just copy the ‘collectAsState’ function, and place a log inside the produceState block
you will check it is only called once for each id
l
val result by produceState(initialValue) {
foo(id).collect { value = it }
}
m
Thats what collectAsState do