Chapters

Hide chapters

Kotlin Multiplatform by Tutorials

Third Edition · Android 15, iOS 18, Desktop · Kotlin 2.1.20 · Android Studio Meerkat

13. Concurrency
Written by Carlos Mota

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now

As an app gets more complex, concurrency becomes a fundamental topic you’ll need to address. learn makes multiple requests to the network — that must be done asynchronously to guarantee they won’t impact the UI.

In this chapter, you’ll learn what coroutines are and how you can implement them.

Concurrency and the Need for Structured Concurrency

Concurrency in programming simply means performing multiple sequences of tasks at the same time. Structured concurrency allows doing multiple computations outside the UI thread to keep the app as responsive as possible. It differs from concurrency in the sense that a task can only run within the scope of its parent, and the parent cannot end before all of its children.

UI-thread secondary thread task #1 #2 #3 segments structured concurrency screen refresh rate coroutine #1 coroutine #2 coroutine #3
Fig. 13.1 — Diagram showing multiple tasks running in structured concurrency.

To improve its performance, these three tasks are running in the same thread, but concurrently to each other. They were divided into smaller segments that run independently.

Structured concurrency recently gained a lot of popularity with the releases of kotlinx.coroutines for Android and async/await for iOS — mainly due to how easy it is now to run asynchronous operations.

Different Concurrency Solutions

There are multiple Kotlin Multiplatform libraries that support concurrency:

Understanding kotlinx.coroutines

Ktor uses coroutines to make network requests without blocking the UI thread, so you’ve already used them unwittingly in the previous chapter.

Suspend Functions

Suspend functions are at the core of coroutines. As the name suggests, they allow you to pause a coroutine and resume it later on, without blocking the main thread.

UO-rtpoup var gaqeezoso lampqJuup() DoisSkeji().maekds { //kneeke wuguapapo } kawmuql qul // dadosoovewelp // pabuzmusp zfi AO bufmalr naf cosjemvq yeoreyk gum wuyjun gursundi qesexem heyiihtuhp Hodiqa soong 0 0 6 8 4 5 noztpBeum() qenbwJuuz() vackqViqulaEsblv() osgadeSixrzTalameItvgj() egcoxuMobwsWuhimeUxrnv()
Yed. 45.3 — Moohwuc kmirubc cro xotjegizs myixt aw e kafkaks mucoayy xazn firuesabir.

Coroutine Scope and Context

Return to FeedPresenter.kt from shared/commonMain/presentation and search for the fetchFeed function:

Coroutine Builders, Scope and Context

You’ve seen how to start a coroutine by calling launch. This function is part of the coroutine builders:

Cancelling a Coroutine

Although you’re not going to use it in learn, it’s worth mentioning that you can cancel a coroutine by calling cancel() on the Job object returned by launch.

Structured Concurrency in iOS

Apple has a similar solution for structured concurrency: async/await.

Using kotlinx.coroutines

It’s time to update learn. In the previous chapter, you learned how to implement the networking layer in Multiplatform. For this, you added the Ktor library and wrote the logic to fetch the Kodeco RSS feed and parse its responses that later update the UI.

Adding kotlinx.coroutines to Your Gradle Configuration

Since Ktor includes the kotlinx.coroutines, you’ve implicitly added this library to the project already.

Troubleshooting kotlinx.coroutines in iOS

As you continue your journey with Multiplatform outside this book, you’ll probably find this error:

Frozen State

In some instances, you might need to freeze your objects when running your iOS app to avoid having the error mentioned above. Once freeze()is called over an object, it becomes immutable. In other words, it can never be changed — allowing it to be shared across different threads.

Working With kotlinx.coroutines

In the app, go to the latest screen. You’ll see a couple of articles grouped into different sections that you can swipe and open, but none of them has an image. It’s time to change this!

Creating a Suspend Function

Start by opening the FeedAPI.kt file from commonMain/data in the shared module.

Creating a Coroutine With launch

Now that you’ve implemented the functions for requesting and parsing data, you’re just missing creating a coroutine, and it’s… launch. :]

Rab. 94.5 — Enpxaol Ups: Ybatxu Ymmuuyn xto Duradq Uyyazyiq
Soz. 39.0 — Oltnuos Awf: Xbeycu Pbyiawb lni Xefubx Unkevmuj

Lun. 86.7 — Qokwpoy Ids: Jzowto Crgiett fmu Robald Axnafgot
Gah. 18.8 — Pehgduy Imy: Hbupxa Fqhauqf mmu Metust Octecsut

Bem. 50.6 — uIP Arw: Nteyli Pwpeimv xki Hepurp Adduqzic
Wox. 43.0 — iUM Ujr: Gxivfo Vywaevh ysu Fuhimv Awfidvuw

Creating a Coroutine With Async

As an alternative to the previous approach where you’re using callbacks to notify the UI when new data is available, you can suspend the fetchLinkImage function until there’s a final result. For that, you’ll need to use async instead of launch.

Lif. 70.2 — Eyvveap Ebd: Lhuwqe Lgdauck hwu Nanirc Ixpicsof
Pod. 37.2 — Awkcoef Idh: Hbucko Dzdaamv tja Xehiyz Igmojdas

Zaw. 26.5 — Luwthiy Ilx: Lbexzu Kznuuzw nzo Tinobj Inlodqak
Jun. 04.7 — Dabwhop Ekk: Bjemmu Xmjiojh dko Jehazf Argufxiy

Fin. 34.1 — oUB Azv: Kyebmo Dlfaocp gfe Zinafy Otledtuj
Kuq. 51.1 — oIH Egr: Dfomzo Qpqoecd fcu Zivovs Iwperlaw

Improving Coroutines Usage for Native Targets

A key point when showing the benefits of using Kotlin Multiplatform on multiple targets is to keep the developer experience as close to using the platform language and tools as possible. When using coroutines on Native targets, you often end up creating wrappers to improve code readability.

Configuring KMP NativeCoroutines

To use this library, you need to add it first to the shared module and then to the iOSApp via the Swift Package Manager. Let’s start by opening the libs.versions.toml file located inside the gradle folder. In the [versions] section define the library versions that you’re going to use:

Using KMP NativeCoroutines With a Suspend Function

Now that all libraries are set, it’s time to update your code. Return to Android Studio and open the FeedPresenter.kt file located in the shared module.

Yuk. 09.3 — iEV Umj: Thaxpi Rdduojf pnu Xaqe Cxgaag
Zeb. 10.8 — uOZ Unk: Clanno Kkpoovj klu Tudi Ggruus

Using KMP NativeCoroutines With Flow

None of the functions in FeedPresenter.kt uses Flow, so the first step is to update the fetchAllFeeds function:

Tak. 01.14 — Apghaad Iyj: Vfapxo Fcpoocr tda Qodo Sdyiib
Jiy. 67.19 — Ifgmaol Emh: Skewni Ywpeuyf qka Gilo Tpguib

Mud. 66.07 — Jipymis Alx: Rziqfa Ykhuazq tvu Kobo Xwjaad
Sul. 86.89 — Vivnquf Ikv: Mvizlo Xlneomv yvi Nuce Hwneas

Gib. 63.65 — eOC Erf: Gcuzpi Smyoacs ylu Weye Sdyioz
Hej. 67.62 — oAL Ixq: Hjocpe Xpxoanq hki Qefu Smvaax

Challenge

Here’s a challenge for you to practice what you’ve learned in this chapter. If you get stuck at any point, take a look at the solutions in the materials for this chapter.

Challenge: Fetch the Article Images From the Shared Module

Instead of requesting the article images from the UI, move this logic to the shared module.

Key Points

  • A suspend function can only be called from another suspend function or from a coroutine.
  • You can use launch or async to create and start a coroutine.
  • A coroutine can start a thread from Main, IO or Default thread pools.
  • The new Kotlin/Native memory model supports running multiple threads on iOS.

Where to Go From Here?

You’ve learned how to implement asynchronous requests using coroutines and how to deal with concurrency. If you want to dive deeper into this subject, try the Kotlin Coroutines by Tutorials book, where you can read in more detail about Coroutines, Channels and Flows in Android. There’s also Concurrency by Tutorials, which focuses on multithreading in Swift, and Modern Concurrency in Swift, which teaches you the new concurrency model with async/await syntax.

Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum here.
© 2026 Kodeco Inc.

You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now