vonox7
07/13/2023, 9:48 AMIterable
to Flow
. To have legacy support, I’m trying to wrap all Flows into existing blocking code. Is there a way to convert a Flow to an Iterator/Iterable, similar as the Iterable.asFlow()
function exists the other way around? The only way I found is to collect the whole Flow to a List and expose that one. However, in the context of database queries this approach seems not to be very ideal.Sam
07/13/2023, 9:52 AMcollect
. So you can’t just create an iterator directly from a flow. If you really need to do this, your best bet is probably to use produceIn
to get a channel, and then make a blocking iterator that receives from the channel. That way the resource management of the flow is handled by the coroutine in which you launch the channel producer job.vonox7
07/14/2023, 11:50 AMproduceIn
. I wrote now those two helper functions (in case anyone else finds this conversation):
@OptIn(FlowPreview::class, DelicateCoroutinesApi::class)
private fun <T> Flow<T>.toBlockingIterator(scope: CoroutineScope = GlobalScope): Iterator<T> {
return this
.produceIn(scope)
.iterator()
.toBlockingIterator()
}
private fun <T> ChannelIterator<T>.toBlockingIterator() = object : Iterator<T> {
override fun hasNext(): Boolean {
return runBlocking { this@toBlockingIterator.hasNext() }
}
override fun next(): T {
return runBlocking { this@toBlockingIterator.next() }
}
}