Concept of Flow in Kotlin
In Kotlin, Coroutines can be used to simplify asynchronous codes.
Coroutine basically helps to implement asynchronous, non-blocking code. For this, we use the suspend function. But the problem with the suspend function is it returns a single object. In such a scenario where you need a data stream, Kotlin has the concept of channel and flow.
Let’s Understand Channel First –
Streaming APIs are almost the exact opposite of REST APIs. When communicating with a REST API, you make a request, and the API sends a response. A streaming API works differently. It connects to a client and continuously listens to new information over time. Twitter, for example, provides a streaming API that you can use to stream tweets in real-time.
You can use Sequence
s for synchronous streams. But you need a different solution for asynchronous streams.
For asynchronous streams, you could use Channel
s from Kotlin Coroutines. Conceptually, you can think of channels as pipes. You send items through one pipe and receive a response through the other. However, a channel represents a hot stream of values. Once again, hot streams start producing values immediately.
Coroutine has introduced Flow API to handle a stream of data that emits values sequentially.
Flow is a type that can emit multiple values sequentially, whereas suspend functions that return only a single value.
- Emitted data must be of the same type.
- Data is emitted sequentially.
- Can use a flow to receive live streams of data.
Let’s see how Flow works in Kotlin :
The Kotlin flow is actually a thread mechanism. It is mainly due to the flow of data that can safely make the network request to produce the next value without blocking the main programming thread. It is basically followed through three types of entities involved in the data streams.
We can create the flows using the flow builder APIs and the function called flow to create manually and emit the new values into the data stream using emit function. Basically, the data source fetches the data automatically at the fixed interval as the suspend function that cannot return multiple consecutive values creates and returns the flow to fulfill the requirement. Sometimes the data source will act as the producer, so the flow builder is executed within the coroutine and thus will be benefited from the same asynchronous APIs, but some restrictions should be applied.
Flows are sequential as the producer is in coroutine type; when calling the suspend function, the producer suspends until the suspend function returns the value. The producer suspends until the network requests are complete, so the result is emitted to the stream. Also, sometimes using the flow builder, the producer cannot emit the values from the different Coroutine contexts.
Let’s create a flow, using flow operator:
We need to create a producer to produce value
fun producer(): Flow<Int> = flow { val list = listOf(1,2,3,4,5,6,7,8,9) list.forEach{ delay(1000) emit(it) } }
To Consume producer we use the collect method.
GlobalScope.launch { val data = producer() data.collect{ Log.d("Value ",it.toString()) } }
Why use Kotlin Flow –
There are already other implementations of the reactive stream specification, such as RxJava. So why use Kotlin Flow? One reason is that you can’t use JVM-specific libraries like RxJava in Kotlin multi-platform projects. But Flow is part of the Kotlin language, so it’s ideal to use in Kotlin multi-platform projects.
Also, Kotlin Flow has fewer operators, but they are much simpler. A single operator can handle both synchronous and asynchronous logic since the block of code that operators accept can be suspended!
And Kotlin Flow is interoperable with other reactive streams and coroutines. Since it’s built on top of coroutines, it provides all the perks of structured concurrency and cancellation. In combination with suspending functions, it produces a simple, readable, and understandable API. It also supports backpressure out of the box.
This blog taught what is so special about Kotlin Flow and how it differs from existing solutions. I hope you’ve enjoyed this blog!
Happy coding!