How to merge flow and channel in Kotlin?

Viewed 1778

I need to create an API, it should be flow, which collects events. The problem is that these events may be from a channel (I need an analog for PublishSubject) and from a flow (which does a network request).

I also not sure if it's the best solution, so let me know if I can make it better.

What am I doing:

My api:

override val statusFlow = trackStatus()

private fun trackStatus(): Flow<State> = flow { ... }

private val deviceChannel = Channel<State>(CONFLATED)

So statusFlow should return a flow from which I can receive data from both flow and channel.

I tried to convert the channel to flow by consumeAsflow, but it doesn't work.

I see a solution as

private fun trackStatus(): Flow<State> = flowOf(channel.toFlow(), flow).flattenMerge()

What is the proper way to do it?

2 Answers
private fun trackStatus() = merge(deviceChannel.recieveAsFlow(), trackStatus)

Definition of merge()from the coroutines library is

/**
 * Merges the given flows into a single flow without preserving an order of elements.
 * All flows are merged concurrently, without limit on the number of simultaneously collected flows.
 *
 * ### Operator fusion
 *
 * Applications of [flowOn], [buffer], [produceIn], and [broadcastIn] _after_ this operator are fused with
 * its concurrent merging so that only one properly configured channel is used for execution of merging logic.
 */
@ExperimentalCoroutinesApi
public fun <T> merge(vararg flows: Flow<T>): Flow<T> = flows.asIterable().merge()

The solution for this case is merge(), as noticed in the province answer, but it won't work like that. You should use BroadcastChannel instead of Channel as the last one can give only one subscription during a lifetime. Also, you should use asFlow() to transform such channel to the flow.

Related