The basic ideas is that coroutines are blocks of code that can be suspended, without blocking a thread.

A coroutine can be suspended only at certain points, called suspension points. That is to say functions with the modifier suspend.

suspend fun answer() {
      println("Hello to you!")
}

they can only be called from coroutines or other functions with suspension points. They cannot be called by normal code.

You can easily eliminate the callback using the suspendCoroutine function. This function works by relying on a Continuation type (cont in the following example), that offers a resume method, which is used to return the expected result.

suspend fun solveAllProblems(params: Params): Result = suspendCoroutine { cont ->
    solveAllProblems(params) { cont.resume(it) }
} 

The advantage of this solution is that now the return type of this computation is explicit., but the computation itself is still asynchronous and does not block a thread.

The Async and Await Mechanism

it provides async and await, that works similarly to the homonym in C#. Typically they are used together, in the case in which an async function returns a meaningful value. First you invoke a function with async, then you read the result with await.

An example of how it can be used.

fun main(args: Array<String>) {

    // runBlocking prevents the closing of the program until execution is completed
    runBlocking {
        // one is of type Deferred<Int>
        val one = asyncAFunction()
        // we use await to wait for the result
        println("The value is ${one.await()")
    }
}

Channels

Channel is conceptually very similar to BlockingQueue. One key difference is that instead of a blocking put operation it has a suspending send, and instead of a blocking take operation it has a suspending receive.

Unlike a queue, a channel can be closed to indicate that no more elements are coming. On the receiver side it is convenient to use a regular for loop to receive elements from the channel.

Conceptually, a close is like sending a special close token to the channel. The iteration stops as soon as this close token is received, so there is a guarantee that all previously sent elements before the close are received:

import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.delay

fun main(args: Array<String>) {
    runBlocking {
        val channel = Channel<Int>()
        launch {
            var y = 1
            for (x in 1..10) {
                y += y
                channel.send(y)
                delay(1000)
            }
            // we close the channel when finished
            channel.close()
        }
        // here we print the received data
        // you could also use channel.receive() to get the messages one by one
        // this loop will continue untill the channel is closed.
        for (y in channel)
            println(y)
    }
}

 

search previous next tag category expand menu location phone mail time cart zoom edit close