Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin Coroutines: Channel vs Flow

I'm recently studying and reading a lot about Flow and Kotlin Coroutines. But I still get confused about when I should use Flow and when I should use Channel.

At the beginning it looked more simple. Working with hot streams of data? Channel. Cold ones? Flows. Same goes if you need to listen to streams of data from more than a single place; if that's the case Channel is the choice to go. There are still a lot of examples and questions.

But recently FlowChannels where introduced, together with tons of methods and classes that encourage the use of Flow, which facilities transforming Channels into Flows and so on. With all this new stuff coming on each Kotlin release I am getting more and more confused. So the question is:

When should I use Channel and when should I use Flow?

like image 326
Francisco Durdin Garcia Avatar asked Dec 19 '19 15:12

Francisco Durdin Garcia


People also ask

What is Channel Flow in Kotlin?

channelFlowIt allows elements to be produced by code that is running in a different context or concurrently. The resulting flow is cold, which means that block is called every time a terminal operator is applied to the resulting flow.

What is flow in coroutines Kotlin?

In coroutines, a flow is a type that can emit multiple values sequentially, as opposed to suspend functions that return only a single value. For example, you can use a flow to receive live updates from a database. Flows are built on top of coroutines and can provide multiple values.

When should I use SharedFlow?

Use SharedFlow when you need a StateFlow with tweaks in its behavior such as extra buffering, replaying more values, or omitting the initial value.

What is coroutines channel?

A channel is conceptually similar to a queue. A channel has a suspending send function and a suspending receive function. This means that several coroutines can use channels to pass data to each other in a non-blocking fashion.


2 Answers

For many use cases where the best tool so far was Channel, Flow has become the new best tool.

As a specific example, callbackFlow is now the best approach to receiving data from a 3rd-party API's callback. This works especially well in a GUI setting. It couples the callback, a channel, and the associated receiving coroutine all in the same self-contained Flow instance. The callback is registered only while the flow is being collected. Cancellation of the flow automatically propagates into closing the channel and deregistering the callback. You just have to provide the callback-deregistering code once.

You should look at Channel as a lower-level primitive that Flow uses in its implementation. Consider working with it directly only after you realize Flow doesn't fit your requirements.

like image 82
Marko Topolnik Avatar answered Sep 19 '22 08:09

Marko Topolnik


In my opinion a great explanation is here (Roman Elizarov) Cold flows, hot channels:

Channels are a great fit to model data sources that are intrinsically hot, data sources that exist without application’s requests for them: incoming network connections, event streams, etc. Channels, just like futures, are synchronization primitives. You shall use a channel when you need to send data from one coroutine to another coroutine in the same or in a different process

But what if we don’t need either concurrency or synchronization, but need just non-blocking streams of data? We did not have a type for that until recently, so welcome Kotlin Flow type...

Unlike channels, flows do not inherently involve any concurrency. They are non-blocking, yet sequential. The goal of flows is to become for asynchronous data streams what suspending functions are for asynchronous operations — convenient, safe, easy to learn and easy to use.

like image 24
tim4dev Avatar answered Sep 17 '22 08:09

tim4dev