Top 9 Kotlin Flow Operators Every Android Developer Needs

Enhance your Android apps with these 9 must-know Kotlin Flow operators for optimal data handling.
Apr 6 2022 · 4 min read

Introduction 

Operators are at the heart of Kotlin Flow, like every reactive Framework. It allows manipulating items as they go from observable to observer.

Here are the 9 very important but less known Kotlin Flow operators with graphics and examples.

We are what we repeatedly do. Excellence, then, is not an act, but a habit. Try out Justly and start building your habits today!

Let's get started!

1. Reduce

Reduce

Reduce operator allows performing operation over all items of the flow to reduce them into one item.

For example, the below reduce function performs sum of all items and thus we get result 6 .

flowOf(1, 2, 3)
    .reduce { acc, value -> acc + value }
    
Output:
6

2. Fold

Fold.png

Similar to reduce but allows result of any type.

For example, here we are starting with a string and performing string concatenation of all items.

flowOf(1, 2, 3)
    .fold("hello", { acc, value -> acc + value })
    
Output:
hello123

3. Debounce

Debounce.png

Debounce operator emits an item from a Flow only if a particular timespan has passed without it emitting another item

For example, consider you are designing a search box and you have a flow of user input.

In that case, you will want search query to fire only when user does not type for 500ms, otherwise you will end up querying only so many times. So as long as user types another character before 500ms passes, debounce will not send that item. However, the last item will always be sent when user does not type anything for 500ms.

flow {
    emit(1)
    delay(90)
    emit(2)
    delay(90)
    emit(3)
    delay(1010)
    emit(4)
    delay(1010)
    emit(5)
}.debounce(1000)

Output:
3, 4, 5

4. Sample

Sample.png

Similar to debounce, it’s also used to filter items from the Flow but it has one important difference — Instead of checking interval from the last item, sample operator will run periodically and will send 1 latest item per interval.

For example, here we have a flow that keeps emitting an item every 50ms and if we apply sample of 100ms, we will get every other item.

flow {
    repeat(10) {
        emit(it)
        delay(50)
    }
}.sample(100)

Output:
1,3,5,7,9

Remember, if we had used debounce here, we will only get item 9 .

5. flatmapMerge

FlatmapMerge.png

flatmapMerge operator maps every item of the Flow with a new Flow provided by transform operation and then merges the items of those flows and flattens it.

Consider the following example

flowOf(1, 2, 3)
    .flatMapMerge { flowOf("$it a", "$it b") }
    
Output:
2a, 2b, 1a, 1b, 3a, 3b

Here Flow of items 1 , 2 and 3 is mapped with a new Flow, that emits 2 items per 1 item of the previous Flow .
Those flows are then merge together and are flattened, so when you collect at the end, you will get flat items from all Flows.

6. flatmapConcat

FlatmapConcat.png

Similar to flatmapMerge but here flows are concatenated instead of merge.

Remember flatmapMerge has better performance as it can process Flows in parallel.

The example above is self explanatory.

7. Buffer

This is a bit hard to understand as this does not really change flow of the items but rather helps with performance.

Consider this example

flowOf("A", "B", "C")
    .onEach  { delay(300) }
    .collect { println("$it") }
    
// Output takes 900ms as all items are processed sequentially

Here we have flow of 3 items and they are emitted immediately.

However, as we have an operator onEach with 300ms delay, collect will process all items sequentially and that means it will take total 900ms for collection.

If we add a buffer between onEach operator and collect , it will create a separate coroutine to collect items from onEach operator in parallel as per the provided capacity of buffer . That will allow us to collect all items in 300ms as all operator operations don’t need to happen sequentially.

flowOf("A", "B", "C")
    .onEach  { delay(300) }
    .buffer(3)
    .collect { println("$it") }
    
// Output takes 300ms as all items are processed in parallel at buffer operator and delivered to collect immediately.

8. Combine

Combine.png

This operator merges two flows with the provided operation function.

Here — Latest item of the Flows are always combined.

As shown in the snippet below, first Flow emits item 1 and 2 . Thus only latest item 2 is combined with the every item of the second Flow.

flowOf("1", "2")
    .combine(flowOf("a", "b", "c"), {a, b -> a + b })
    
Output:
2a, 2b, 2c

9. zip

Zip.png

Similar to combine , this also merges two Flows but it will broadcast one item when both Flow emits 1 item each.

The resulting flow completes as soon as one of the flows completes and cancel is called on the remaining flow.

flowOf("1", "2")
    .zip(flowOf("a", "b", "c"), {a, b -> a + b })
    
Output:
1a, 2b

As shown here, only two zipped items are emitted from the resulting flow as first Flow has only two items.

Conclusion 

Operators form the core of Kotlin Flow, serving a crucial role akin to that in every reactive framework. They provide the essential functionality for manipulating items as they transition from the observable source to the observer, enabling developers to efficiently handle and transform data streams in a reactive programming model. 

This makes Kotlin Flow a powerful tool for creating responsive and resilient applications.

That’s it for today, hope you learned something new!

Thanks for your support!


Code, Build, Repeat.
Stay updated with the latest trends and tutorials in Android, iOS, and web development.
jimmy image
Jimmy Sanghani
Jimmy Sanghani is a tech nomad and cofounder at Canopas helping businesses use new age leverage - Code and Media - to grow their revenue exponentially. With over a decade of experience in both web and mobile app development, he has helped 100+ clients transform their visions into impactful digital solutions. With his team, he's helping clients navigate the digital landscape and achieve their objectives, one successful project at a time.
jimmy image
Jimmy Sanghani
Jimmy Sanghani is a tech nomad and cofounder at Canopas helping businesses use new age leverage - Code and Media - to grow their revenue exponentially. With over a decade of experience in both web and mobile app development, he has helped 100+ clients transform their visions into impactful digital solutions. With his team, he's helping clients navigate the digital landscape and achieve their objectives, one successful project at a time.
canopas-logo
We build products that customers can't help but love!
Get in touch
background-image

Get started today

Let's build the next
big thing!

Let's improve your business's digital strategy and implement robust mobile apps to achieve your business objectives. Schedule Your Free Consultation Now.

Get Free Consultation
footer
Follow us on
2024 Canopas Software LLP. All rights reserved.