WalzoneInterview Prep
📞 Interviewing soon? Practice with a realistic AI mock phone interview — it calls you, then scores you. First 15 min FREE →

Kotlin · Expert · question 78 of 100

What are the main differences between the kotlinx.coroutines.channels API and the kotlinx.coroutines.flow API? When should you use each?

📕 Buy this interview preparation book: 100 Kotlin questions & answers — PDF + EPUB for $5

The ‘kotlinx.coroutines‘ library provides two APIs for working with asynchronous and potentially infinite data streams: ‘channels‘ and ‘flow‘. Both APIs are built on top of coroutines and provide similar functionality, but differ in some important ways.

The ‘channels‘ API provides a way to communicate between coroutines through a single, coordinated stream. Channels can be used to transmit any type of data, and can be closed to indicate that no more data will be sent. Channels also support backpressure, which means that the sender of data can be suspended if the receiver is not keeping up. Here’s an example of using channels to pass messages between coroutines:

val channel = Channel<String>()
launch {
    channel.send("Hello")
    channel.send("World")
    channel.close()
}
for (message in channel) {
    println(message)
}

This code creates a new ‘Channel‘ that can send and receive ‘String‘ values. It then launches a coroutine that sends two messages and closes the channel. Finally, a loop is used to receive each message from the channel and print it out. The ‘for‘ loop is able to use the channel directly thanks to ‘Channel‘ implementing the ‘Iterator‘ interface.

The ‘flow‘ API, on the other hand, provides a way to represent potentially infinite streams of data as a series of events. Flows do not support sending data between coroutines directly, but rather provide a way to transform and manipulate data streams using operators similar to those in RxJava or Java 8 Streams. For example:

val numbers = flowOf(1, 2, 3, 4, 5)
    .map { it * 2 } // double each number
    .filter { it % 3 == 0 } // only keep multiples of 3
    .take(2) // only take the first two numbers
    .toList() // convert to a list

println(numbers) // [6, 12]

This code creates a new flow that emits the numbers 1 through 5, doubles each number, keeps only multiples of 3, takes the first two values, and converts them to a list. The ‘map()‘, ‘filter()‘, and ‘take()‘ operators all return new flows that represent the transformed data stream, without modifying the original flow.

So when should you use each API? Generally speaking, ‘channels‘ are a good fit for cases where you need to communicate between coroutines in real-time, such as passing messages or coordinating work. ‘flows‘, on the other hand, are better suited for cases where you have a potentially infinite stream of data that needs to be transformed or processed in some way, such as reading from a database or reacting to user inputs.

Reading is step one. Saying it out loud is the interview. Our AI interviewer calls your phone and runs a realistic Kotlin interview — then scores it.
📞 Practice Kotlin — free 15 min
📕 Buy this interview preparation book: 100 Kotlin questions & answers — PDF + EPUB for $5

All 100 Kotlin questions · All topics