.combine is a function provided by Kotlin’s Flow API. It allows us to combine two or more flows into a single flow, emitting values whenever any of the source flows emit a new value. This is useful for scenarios where you want to react to changes in multiple data sources and perform some operation on the combined data. Let’s look at a real-world example —

Consider a social media app where users can like, comment, and post. The function summarizedNotifications() combines these activities into concise notifications. The sequence of results will print as follows —

  1. Likes and comments are combined for each corresponding post.
  2. The combined data is then merged with the posts, forming comprehensive notifications.

The use of the delay function simulates real-time interactions for a more authentic user experience. For instance, users liking a post followed by a few comments followed by more reactions. This simulation adds a layer of realism to your app’s notification system.

.combine() diagrammatic representation

Code

private fun summarizedNotifications() {
viewModelScope.launch {
val likesActivity: Flow<Like> = flowOf(*likesList.toTypedArray()).onEach {
delay(50)
}
val commentsActivity: Flow<Comment> = flowOf(*commentsList.toTypedArray()).onEach {
delay(200)
}
val postsActivity: Flow<Post> = flowOf(*postsList.toTypedArray()).onEach {
delay(100)
}
likesActivity.combine(commentsActivity) { like, comment ->
"${like.userName} reacted with ${like.reactionName} on ${like.postTitle}\n" +
"and ${comment.userName} commented ${comment.commentText} on ${comment.postTitle}"
}.combine(postsActivity) { activity, post ->
Log.i("Notification", "$activity .. Also ${post.userName} added a new post '${post.postTitle}'")
}.collect()
}
}

Example Data Input

You can find the data class and example data here.

Example Data Output

Rahul reacted with ❤ on Starry Night Photography
and Alice commented This is amazing! on Exploring the Cosmos .. Also Alice added a new post 'Exploring the Cosmos'
Rahul reacted with ❤ on Starry Night Photography
and Alice commented This is amazing! on Exploring the Cosmos .. Also Bob added a new post 'Starry Night Photography'
Grace reacted with ? on Astronomy Basics
and Alice commented This is amazing! on Exploring the Cosmos .. Also Bob added a new post 'Starry Night Photography'
Charlie reacted with ? on Starry Night Photography
and Alice commented This is amazing! on Exploring the Cosmos .. Also Bob added a new post 'Starry Night Photography'
Charlie reacted with ? on Starry Night Photography
and Alice commented This is amazing! on Exploring the Cosmos .. Also Charlie added a new post 'Astronomy 2 Basics'
...
...
...

Based on the delays provided in the code, likes will be emitted every 50 milliseconds, comments every 200 milliseconds, and posts every 100 milliseconds. The delay values influence the order in which the activities are emitted and combined.

As you can see, the activities are emitted in the order of the delays — likes, posts, and then comments. This is why Alice’s first like (refer input data) doesn’t appear first in the output. The delay of 50 milliseconds for likes causes the subsequent activities to be emitted and combined. As a result, the combination that striked (Rahul’s like) after her like at 100ms is the one that is actually printed.

Tip? — Do try .combine() with all three flows in the same function call to see the difference.

combine(likes, comments, posts) {likes, comments, posts -> 
// log here
}.collect()

Source link