Going deep on Flows & Channels — Part 1: Streams

Here, in a series of articles, we will dive deeper into the Channel’s and Flow’s API.
There is a bit of confusion out there with people trying to define is they are hot or cold or in-between or whatever. But, what I really believe is that it doesn’t matter which type is each one, instead, you have to understand how they work and what problems they solve. Then, you may choose one or another, but staying confident with yourself: you will know what you’re doing.
The series will have 5 articles:
- Part 1: Cold & Hot Streams.
- Part 2: Flows.
- Part 3: Channels.
- Part 4: BroadcastChannels
- Part 5: StateFlows and conclusions.
Lastly, I have been working on a GitHub Repository where you can find some examples of Flow and Channels implementation, and an Example App (that looks like a cheap Twitter) where we simulate a real use case for them.
Concerning the Example App, you will find in the repository three different branches that implement 3 different solutions for one common problem: hot streams. Don’t forget to check it out! There are basic usages of Channel, BroadcastChannel and StateFlow.
Let’s begin with the first part, Streams!
Streams
There is a lot of confusion when we try to define a hot and cold stream. We like to say some definitive statements like “Flow for Cold Streams and Channel for Hot Streams”, but when we start working with them, we see that the line that separates both Components is not that clear.
Cold & Hot Streams
There are two types of streams: Cold and Hot ones. In this section, I’ll describe the main differences and the characteristics of each.
There are some great and concise articles that you can read about this (and I used them to write this section): 1, 2, 3.
Main differences
There are, in my opinion, three main differences that will help to define whether a Stream is Cold or Hot.
- Where the data is produced: the data can be produced inside or outside the stream. In other words, the data exists (or doesn’t) no matter if you use the Stream or not.
- How many receivers, at the same time, can get the data: here, we talk about unicast or multicast mechanisms.
- Laziness: when the stream starts to emit values. Can it start eagerly or it will start when I request for it?
We will see in the following articles that, maybe, the last one is the most convenient way to differentiate streams in Flow & Channel’s API.
Cold Streams
We can say that, in the cold streams, all the data is produced inside the stream.
A cold stream has one and only one subscriber and only emits values to that subscriber. Furthermore, that subscriber is the one that initializes the stream. So, we can say that we have a unicast mechanism here.
For each new subscription that the stream receives, a new execution of its code is triggered, and it’ll be independent of the previous ones. So, we can say that we can have multiple instances of the same stream, and they’re fully independent.
It’s important to notice that the lines of code that will be executed to produce some values are the same for all the subscribers, it doesn’t depend on who is calling.
And, lastly, we can say that a cold stream is a lazy stream: the emission of values starts only when someone subscribes to it. In other words, it begins when someone says “hey, start emitting that I’m here listening”.
A great analogy of a cold stream can be a CD:
- We have 1 CD for each listener → 1 stream for 1 subscriber
- The CD ends when the listener stops the reproduction → the stream ends when the subscriber disconnects
- The songs are the same for all the listeners, no matter the moment they start listening to → the data emitted is the same for all the subscribers, no matter the moment they subscribe
Hope you understand what a cold stream is and how does it work. Let’s review the hot ones now.
Hot Streams
We can say that, in the hot streams, all the data is produced outside the stream. This data can exist without the stream and, generally, it comes from external components.
A hot stream can have zero or more subscribers, and emits values to all of them at the same time. So, we can say that we have a multicast mechanism here.
There is only one emission for all the subscribers, and they don’t initialize it, instead, they attach to it and start listening. Depending on the moment they attach, they can receive different data. What happens if nobody is listening? Well, nothing really: the data gets lost, but nobody cares!
And, lastly again, we can say that a hot stream is an eager stream: the emission of values always starts, no matter if there is someone subscribed or not. In other words, someone says “let’s listen to the stream emissions”.
A great analogy of a hot stream can be a Radio Station:
- There is only 1 radio station for all the listeners → 1 stream for all the subscribers
- The radio continues producing content even if nobody is listening → the stream continues even if there are no subscribers
- The song that the listeners receive depends on the moment they start listening to the radio → the data received by the subscribers depends on the moment they subscribe
And that’s it for hot streams. Did you notice the differences, right?
In-between streams
This is a definition that I found and I want to mention.
Some cold streams aren’t as cold as the definition of cold mentions. With those, the data received by the subscribers could depend on the moment they subscribe. Something like a hot stream feature in a cold stream.
Difference between Cold & Hot Streams by Roman Elizarov
Roman posted an interesting article and will give us another perspective of how to compare these streams. You can see the full article here.
There, at a very high level, he takes two concepts to differentiate cold and hot streams: the existence of the data source and the synchronization.
For hot streams (Channels), he said:
- The data source exists without the application’s request for them. For example, we have a remote server with a database that holds data and retrieves it using a REST API.
- With hot streams, you need synchronization, because there different actors that send and consume information, and they must be synchronized. In the case of Channels, for example, you need to synchronize different coroutines with possible different execution contexts and scopes.
For cold streams (Flows), he said:
- The data source is not active before the stream’s request, or after the stream ends.
- We don’t need concurrency or synchronization, just a sequential and non-blocking stream of values.
And that’s for now!
Hope you can clearly define what a cold or hot stream is (or not?).
I prepared this introduction just to, in the following articles, evaluate if the Flow & Channel APIs expose a real cold and hot stream, or instead we have to know how they work and, starting from there, choose what to use.
See you later! And, if you like it, you can share!
Special thanks to the MediaMonks Android team that gives feedback.