Book Image

Simplifying Android Development with Coroutines and Flows

By : Jomar Tigcal
Book Image

Simplifying Android Development with Coroutines and Flows

By: Jomar Tigcal

Overview of this book

Coroutines and flows are the new recommended way for developers to carry out asynchronous programming in Android using simple, modern, and testable code. This book will teach you how coroutines and flows work and how to use them in building Android applications, along with helping you to develop modern Android applications with asynchronous programming using real data. The book begins by showing you how to create and handle Kotlin coroutines on Android. You’ll explore asynchronous programming in Kotlin, and understand how to test Kotlin coroutines. Next, you'll learn about Kotlin flows on Android, and have a closer look at using Kotlin flows by getting to grips with handling flow cancellations and exceptions and testing the flows. By the end of this book, you'll have the skills you need to build high-quality and maintainable Android applications using coroutines and flows.
Table of Contents (11 chapters)
1
Part 1 – Kotlin Coroutines on Android
6
Part 2 – Kotlin Flows on Android

The new way to do it – coroutines and flows

In this section, you will learn about the recommended approach for Android asynchronous programming: using coroutines and flows. Coroutines is a Kotlin library you can use in Android to perform asynchronous tasks. Coroutines is a library for managing background tasks that return a single value. Flows are built on top of coroutines that can return multiple values.

Kotlin coroutines

Coroutines is a Kotlin library for managing background tasks, such as making network calls and accessing files or databases, or performing long-running background tasks. Using Kotlin coroutines is Google’s official recommendation for asynchronous programming on Android. Their Android Jetpack libraries, such as Lifecycle, WorkManager, and Room-KTX, now include support for coroutines. Other Android libraries, such as Retrofit, Ktor, and Coil, provide first-class support for Kotlin coroutines.

With Kotlin coroutines, you can write your code in a sequential way. A long-running task can be made into a suspend function. A suspend function is a function that can perform its task by suspending the thread without blocking it, so the thread can still run other tasks. When the suspending function is done, the current thread will resume execution. This makes the code easier to read, debug, and test. Coroutines follow a principle of structured concurrency.

You can add coroutines to your Android project by adding the following lines to your app/build.gradle file dependencies:

implementation "org.jetbrains.kotlinx:kotlinx-coroutines-
  core:1.6.0"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-
  android:1.6.0"

kotlinx-coroutines-core is the main library for Kotlin coroutines, while kotlinx-coroutines-android adds support for the main Android thread (Dispatchers.Main).

To mark a function as a suspending function, you can add the suspend keyword to it; for example, here we have a function that calls the fetchText() function, which retrieves text from an endpoint and then displays it in the UI thread:

fun fetchText(): String {
  ...
}

You can make the fetchText() function a suspending function by prefixing the suspend keyword, as follows:

suspend fun fetchText(): String { ... }

Then, you can create a coroutine that will call the fetchText() suspending function and display the list, as follows:

lifecycleScope.launch(Dispatchers.IO) {
    val fetchedText = fetchText()  
    withContext(Dispatchers.Main) {
      displayText(fetchedText)
    }
}

lifecycleScope is the scope with which the coroutine will run. launch creates a coroutine to run in Dispatchers.IO, which is a thread for I/O or network operations.

The fetchText() function will suspend the coroutine before it starts the network request. While the coroutine is suspended, the main thread can do other work.

After getting the text, it will resume the coroutine. withContext(Dispatchers.Main) will switch the coroutine context to the main thread, where the displayText(text) function will be executed (Dispatchers.Main).

In Android Studio, the Editor window identifies the suspend function calls in your code with a gutter icon next to the line number. As shown in lines 13 and 15 in Figure 1.6, the fetchText() and withContext() lines have the suspend function call gutter icon:

Figure 1.6 – Android Studio suspend function call gutter icon

Figure 1.6 – Android Studio suspend function call gutter icon

You can learn more about Kotlin coroutines in Chapter 2, Understanding Kotlin Coroutines.

In the next section, you will learn about Kotlin Flows, built on top of coroutines, which can return multiple sequences of values.

Kotlin Flows

Flow is a new Kotlin asynchronous stream library that is built on top of Kotlin coroutines. A flow can emit multiple values instead of a single value and over a period of time. Kotlin Flow is ideal to use when you need to return multiple values asynchronously, such as automatic updates from your data source.

Flow is now used in Jetpack libraries such as Room-KTX and Android developers are already using Flow in their applications.

To use Kotlin Flows in your Android project, you have to add coroutines. An easy way to create a flow of objects is to use the flow{} builder. With the flow{} builder function, you can add values to the stream by calling emit.

Let’s say in your Android app you have a getTextFromNetwork function that fetches text from a network endpoint and returns it as a String object:

fun getTextFromNetwork(): String { ... }

If we want to create a flow of each word of the text, we can do it with the following code:

private fun getWords(): Flow<String> = flow {
  getTextFromNetwork().split(" ").forEach {
    delay(1_000)
    emit(it)
  }
}

Flow does not run or emit values until the flow is collected with any terminal operators, such as collect, launchIn, or single. You can use the collect() function to start the flow and process each value, as follows:

private suspend fun displayWords() {
          getWords().collect {
          Log.d("flow", it)
           }
}

A visual representation of this flow is shown in the following figure:

Figure 1.7 – Kotlin Flow visual representation

Figure 1.7 – Kotlin Flow visual representation

As you can see in Figure 1.7, as soon as the getWords() flow emits a string, the displayWords function collects the string and displays it immediately on the logs.

You will learn more about Kotlin Flows in Chapter 5, Using Kotlin Flows.

In this section, you learned about Kotlin coroutines and flows, the recommended way to carry out asynchronous programming in Android. Coroutines is a Kotlin library for managing long-running tasks in the background. Flow is a new Kotlin asynchronous stream library, built on top of coroutines, that can emit multiple values over a period of time.