What is the right way to handle `Flow` that comes ...
# compose
l
What is the right way to handle
Flow
that comes from view model? I have a
Flow
that produces values for
LazyColumn
. Do I have to put the values into a
SnapshotStateList
or can I feed the
LazyColumn
on the fly with the values? How would I do this?
z
You mean after doing
collectAsState
?
1
Oh, the flow produces individual values, and you want to aggregate them into a list?
l
Isn't there some other construct to handle flows? I would need to collect the flow either in vm or in UI. Next question would be if I can feed the LazyColumn directly with a single item or if I have to aggregate them into a List/SnapshotStateList?
Oh, the flow produces individual values, and you want to aggregate them into a list?
Yes if I have to aggregate them.
z
The
SnapshotStateList
you suggested could work, but you could also use the flow scan operator to create the list on the flow side.
So e.g.
Copy code
val allValues by remember(values) {
  values.scan(emptyList()) { list, value -> list + value }
}.collectAsState(emptyList())
where
values
is your original flow
Or
Copy code
val allValues by remember { mutableStateListOf() }
LaunchedEffect(values) {
  values.collect { allValues += it }
}
l
Looks satisfying. When working with lists in compose, is it common to create a new list on every new value?
z
It's pretty common when working with functional programming in general, flows, rx, channels, any sort of cross-thread communication, or any other architecture that encourages immutable data.
👍 1
l
Copy code
val allValues by remember { mutableStateListOf() }
LaunchedEffect(values) {
  values.collect { allValues += it }
}
Taking this example. Where is the different, when collecting the flow in the vm and store the items in a
val items = mutableStatelistOf()
. From UI, I could use
items
directly.
z
the mutable state list is less wasteful because it's not copying lists every time, but that's not the only difference between these two approaches. You should also consider whether you want your view model/presentation layer to expose a flow of individual values, or the accumulated complete list. I would probably do the latter in most cases. And then it depends whether your codebase lets you use compose's state values in that layer or if you need to stick to flow
So if you did the
mutableStateListOf
in your vm, that's fine, but you'd need to manage the coroutine that did the collection somehow (maybe
.launchIn(viewModelScope)
?)
l
So if you did the 
mutableStateListOf
 in your vm, that's fine, but you'd need to manage the coroutine that did the collection somehow (maybe 
.launchIn(viewModelScope)
?) 
Would be a great candidate for
init
block
z
I generally like to avoid doing side effects like that in constructors/init. It makes some code harder to read ("i just created this object, i haven't called any methods, why are things happening?!") and trickier to test, etc.
But yea you could technically do it there
l
Note that SnapshotStateList does copy in some sense, it uses PersistentList(ImmutableList) of kotlinx.collections under the hood which is copied on every operations but optimizes tail appending memory space AFAIK..?
z
Yea, basically i think the amount of list items that have to be copied stays mostly constant as the list grows, but that's an implementation detail.
l
Thanks Zach