https://kotlinlang.org logo
#coroutines
Title
# coroutines
m

Mohamed Ibrahim

03/02/2020, 3:52 PM
I have a
Flow<Product>
which emits one by one, how I make it to collect those in list so I could receive a list in
collect()
l

louiscad

03/02/2020, 3:55 PM
You can create a custom operator that creates an empty mutable list before collecting the source flow, and emits the list after each collected element added. You can also use
scan
.
m

Mohamed Ibrahim

03/02/2020, 4:04 PM
what do you think of this
Copy code
fun <T> Flow<T>.intoList(): Flow<List<T>> {
    return flow {
        val bag = arrayListOf<T>()
        collect {
            bag.add(it)
        }
        emit(bag)
    }
}
s

streetsofboston

03/02/2020, 4:11 PM
Note that works only if the source Flow ends/completes. Otherwise, nothing will be ever emitted
m

Mohamed Ibrahim

03/02/2020, 4:14 PM
why
s

streetsofboston

03/02/2020, 4:18 PM
If the source Flow does not end, your call to
collect
will suspend forever. It will keep adding items to
bag
, but
emit(bag)
will never be called in that case
• Your source Flow starts as soon as your code calls
collect
on it, and your
collect
call suspends. • The lambda provided to your
collect
call will be called each time your source/producer Flow calls
emit
. • In the mean time your call to
collect
remains suspended. • Your call to
collect
resumes when the lambda provided to your source/producer Flow returns/*ends*.
l

louiscad

03/02/2020, 4:37 PM
@Mohamed Ibrahim You need to call
emit
after each call to
add
inside the
collect
lambda.
s

streetsofboston

03/02/2020, 4:45 PM
That would be like a
scan
operator, emitting a growing list each time. I think he was more thinking about a final terminating (and suspending)
toList()
method on the source Flow…. but I could be wrong…
l

louiscad

03/02/2020, 6:08 PM
That one already exists @streetsofboston
s

streetsofboston

03/02/2020, 6:12 PM
I wasn't sure it already existed...😀 But it seems the original poster has some issue with how Flows and their collection exactly works...
m

Mohamed Ibrahim

03/02/2020, 7:59 PM
The issue with me that if I used toList() I have to use try catch. and may I still have RxJava concepts in mind. And not breaking the stream was my purpose
I don't know if that even correct for Flow
The scan operator is very handy here is an example of it
Copy code
val toList = 
flowOf(1, 2,3).scan(emptyList<Int>()) { acc, value -> acc + value }.toList()
💯 1
s

streetsofboston

03/02/2020, 10:44 PM
Yup, if you are looking on how that list grows for each emission, using
scan
is a great way to do so. But if you just need get one final list of all emissions (without any intermediate ones),
toList()
is your friend, but that requires the flow to end (since a list can only contain a finite amount of items).
3 Views