Hey Kotliners π,
Kotlin Coroutines is a very powerful library that comes along with a lot of APIs which provide out-of-box functionalities. In this article, we will look at one of the APIs i.e. select
expression.
What is a select
expression? π€¨
While application development, you may have several suspended functions and you want to have a single business logic that operates on the results of the suspended functions as they complete. The coroutines library provides this capability through the select function. The select function acts as a type-safe builder, where extension functions are provided that can register callbacks on the suspendable functions.
In Kotlin coroutines, the "select" expression makes it possible to await multiple suspending functions simultaneously and selects the first result that becomes available. It's a suspending function that is suspended until one of the clauses is either selected or fails.
The select expression can be used in some of the use cases while application development. For example,
- There's a scenario in which you want to process "X" thing when anyone from data "A" or "B" becomes available first.
- You are running a few operations concurrently and whichever finishes (or returns result) first, proceed with the result of the winner operation i.e. data race.
...And a lot of use cases like this.
Let us explore it more by looking at examples.
Using it β¨
As we discussed some use cases, the very simple example of using select
could be like thisππ».
fun main() = runBlocking<Unit> {
val winner = select<String> {
data1().onAwait { it }
data2().onAwait { it }
}
println("The winner = $winner") // prints "The winner = Hello"
}
fun data1() = GlobalScope.async {
delay(1000)
"Hello"
}
fun data2() = GlobalScope.async {
delay(2000)
"World"
}
In this example:
data1()
anddata2()
are function that returnDeferred<String>
in whichdata1
takes 1000ms to load data anddata2
takes 2000ms.- In the "select" builder,
onAwait()
clause is used to wait for the result. - As
data1()
returns the result, its value ("Hello") is selected since it's completed first. Thus it's a winner.
Let's take another example in which you want to perform a certain operation after a user performs some interaction on UI among the multiple choices. The select expression can be used like this ππ»
suspend fun awaitCloseDialog() {
select<Unit> {
async { dialog.closeButton.awaitClick() }.onAwait { }
async { dialog.okButton.awaitClick() }.onAwait { }
}
dialog.dismiss()
}
In this example, a dialog
will be get dismissed when either the "Close" button is clicked or the "OK" button is clicked.
You can also select results from the values produced by the Channel APIs like the following ππ».
fun main() = runBlocking<Unit> {
repeat(5) {
val number = select<Int> {
evenChannel.onReceive { it }
oddChannel.onReceive { it }
}
println(number) // prints "0 1 3 2 5"
}
}
val evenChannel = GlobalScope.produce<Int> {
repeat(10) {
delay(1000)
if (it % 2 == 0) {
send(it)
}
}
}
val oddChannel = GlobalScope.produce<Int> {
repeat(10) {
delay(500)
if (it % 2 != 0) {
send(it)
}
}
}
In this example, the evenChannel
produce even numbers after 1000ms and oddChannel
produces numbers after 500ms. Thus you can see that odd numbers are selected more often than even numbers.
These were some basic examples of select expression.
Note: When multiple clauses can be selected at the same time, the first one which was executed of them gets selected on the priority i.e. the select function is biased toward the first clause. Use
selectUnbiased
for an unbiased selection among the clauses which simply shuffles/randomizes the selection.
List of supported select methods
These are APIs from coroutines that are supported for select expression clauses.
Receiver | Suspending function | Select clause |
Job | join | onJoin |
Deferred | await | onAwait |
SendChannel | send | onSend |
ReceiveChannel | receive | onReceive |
ReceiveChannel | receiveCatching | onReceiveCatching |
- | delay | onTimeout |
You can visit official documentation for exploring more available APIs around the select
expression.
Final thoughts π§
The select
expression can be used in many use cases while developing applications in Kotlin. But remember that Currently this API is experimental which means that the design of the corresponding declarations has open issues which may (or may not) lead to their changes in the future.
I hope you liked this article. Please share this article if you found this helpful.
Sharing is caring! π«Άπ»
Thank you! π