0% found this document useful (0 votes)
36 views3 pages

Step 13749 Coroutine - Builders - Overview

Coroutine builders allow suspending functions to be called from regular non-suspending code. The runBlocking builder executes suspending code synchronously and waits for it to finish before returning. The launch builder executes suspending code asynchronously and returns a Job object immediately without waiting. Jobs can be used to check status and cancel coroutines.

Uploaded by

sefsdfdf
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
36 views3 pages

Step 13749 Coroutine - Builders - Overview

Coroutine builders allow suspending functions to be called from regular non-suspending code. The runBlocking builder executes suspending code synchronously and waits for it to finish before returning. The launch builder executes suspending code asynchronously and returns a Job object immediately without waiting. Jobs can be used to check status and cancel coroutines.

Uploaded by

sefsdfdf
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 3

Computer science → Programming languages → Kotlin → Concurrency and parallelism → Concurrency

Coroutine builders: overview


Theory Practice 0% completed, 0 problems solved

Theory Verify to skip Start practicing

14 minutes reading

You're starting a new topic!


Each topic introduces one new concept with a short article. Read it, then apply what
you've learned by solving a few problems. Practice makes perfect!

As you remember, a regular non-suspending function cannot call a suspending function directly. At the
same time, many types of applications start with regular functions, so how then can we use
coroutines? The solution for this is coroutine builders.

A coroutine builder is a function that takes a suspending function as its parameter and schedules its
execution. The builder can be called from regular code, acting as a bridge between suspending and
non-suspending planes. In this topic, we'll discuss the two most common builders and learn how to use
them to perform suspending operations, both synchronously and asynchronously.

O
§1. Coroutines usage
Let's say we need to perform some large operation that suspends in multiple places, for example, get a
file from a server, save it to the disk, etc. At each step of this operation, we want to use coroutines to
have concise code without callbacks, so we need to build a parent coroutine. We want to wait till the
M
operation is complete before we can notify the user and finish the app.

As we know, calling the suspending function directly won't work:

1 import kotlinx.coroutines.delay // kotlinx.coroutines is the primary package for c


2
3 // pretend we're busy here, there would be some long operation in real-life code
4 // but delay() is a suspending function so it's a fair example
5 suspend fun doLotsOfWorkWithFile(file: String) = delay(5_000)
E
6
7 fun main() {
8 println("Preparing for hard work...")
9 doLotsOfWorkWithFile("a") // compilation error here !
10 println("Work is done!")
11 }
D

To solve that problem, we can use the runBlocking builder.

§2. Wait for suspending code: runBlocking


runBlocking is a regular function that takes exactly one suspending function, executes it, waits until
it finishes, and returns its result. This is exactly what we need in our situation! Let's give it a try:

1 import kotlinx.coroutines.delay
2 import kotlinx.coroutines.runBlocking
3
4 suspend fun doLotsOfWorkWithFile(file: String) = delay(5_000)
5
6 fun main() {
7 runBlocking { // this lambda is our root suspending funct
8 println("Starting coroutine.") // it can contain regular functions
9 doLotsOfWorkWithFile("a") // and suspending functions as well
10 }
11 println("Work is done!")
12 }

As you can see, our main function is not suspending, but now it compiles and runs properly: the delay
between the two outputs is 5 seconds. We can say that we are waiting for the coroutine to finish in the
regular code.

Sometimes, all our code is potentially suspending. In that case, we can wrap everything with the
runBlocking builder:

Created with Pdfcrowd HTML to PDF API


1 fun main() = runBlocking { // here coroutine begins
2 println("Starting coroutine.")
3 doLotsOfWorkWithFile("a")
4 println("Work is done!")
5 } // here it ends

In fact, this is a common approach for simple apps or tests. But what if we need to do multiple
independent operations, for example, receive two files from two different servers? We can still run
them using blocking:

1 fun main() = runBlocking {


2 println("Starting coroutine")
3 doLotsOfWorkWithFile("a") // there is no limit on how many suspending
4 doLotsOfWorkWithFile("b") // functions a suspending function can call
5 println("Work is done!")
6 }

Does it work faster than regular code? No! Suspending functions are executed sequentially, and we're
waiting for the whole coroutine to finish. It will take about 10 seconds. To launch different operations
that can be suspended independently we can use another builder — launch .

§3. Fire and forget: launch

O
launch is similar to runBlocking in terms of syntax but has a different purpose: it does not wait for
the coroutine to finish but immediately returns a special handler to the launched coroutine called a
Job. The coroutine itself continues working, but we can check the status or even cancel it through a
Job object. We'll talk about scopes later, now we are using GlobalScope for example purposes only.
Let's take a look:
M1
2
3
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
4
5 fun main() {
6 println("Starting")
7 val importantJob = GlobalScope.launch {
8 doLotsOfWorkWithFile("important_file") // waits for 5s
E
9 println("Important file processed") // will only print after 5s
10 }
11 val notImportantJob = GlobalScope.launch {
12 doLotsOfWorkWithFile("optional_file") // also waits
13 println("Optional file processed")
14 }
15 println("Finishing")
D

16 } // exits immediately, not waiting f

This code will not print Important file processed or Optional file processed because main
doesn't wait for the launched coroutines and returns immediately. The output would be:

Starting
Finishing

To wait for the result, we still need to block the main function:

1 fun main() {
2 println("Starting")
3 val importantJob = GlobalScope.launch {
4 doLotsOfWorkWithFile("important_file") // waits for 5s
5 println("Important file processed")
6 }
7 val notImportantJob = GlobalScope.launch {
8 delay(500) // add extra delay
9 doLotsOfWorkWithFile("optional_file") // so total wait is 5.5s
10 println("Optional file processed")
11 }
12 runBlocking { // block main until 6s delay is over
13 delay(6_000) // by this time both jobs should fin
14 }
15 println("Finishing")
16 }

Now it will work as expected and print this:


Created with Pdfcrowd HTML to PDF API
Starting
Important file processed
Optional file processed
Finishing

Notice that we don't have to wait 10 seconds to get both files processed as we did with runBlocking .
Moreover, if we decrease the wait time from 6s to 5.1s, the app will process the important file but not
the optional one. In real life, we'd actually need to wait for a job to finish, not for a specific time, and we
can do that with join().

1 fun main() {
2 println("Starting")
3 val importantJob = GlobalScope.launch {
4 doLotsOfWorkWithFile("important_file")
5 println("Important file processed")
6 }
7 val notImportantJob = GlobalScope.launch {
8 doLotsOfWorkWithFile("optional_file")
9 println("Optional file processed")
10 }
11 // we still have to use runBlocking because join() is a suspending function
12 runBlocking {
13 importantJob.join() // join() suspends until the job is done

O
14 }
15 notImportantJob.cancel() // cancel non important job if it's not done yet
16 println("Finishing")
17 }

With this approach, we can launch multiple independent operations simultaneously and wait for their
results later, cancel them, or do something else. Job is a powerful tool here, and it provides way more
features than we can discuss in this topic: we will consider it in another one, and meanwhile, you can
M
check the official documentation to learn more.

§4. Conclusion
Let's recap what we know about coroutine builders:

Builders can start coroutines from regular code. They bridge the gap between the regular and
E
suspending functions.
To wait for the result of the suspending code, use runBlocking .
To run suspending code without having to wait for it to finish, use launch .
To control the launched coroutine and check its status, use Job that launch returns.

43 users liked this piece of theory. 4 didn't like it. What about you?
D

Start practicing Verify to skip


Provided by: JetBrains Academy

Report a typo

Comments (0) Useful links (0) Hide discussion

No useful links yet.

Created with Pdfcrowd HTML to PDF API

You might also like