Android Networking: Beyond the Basics

Sep 8 2022 · Kotlin 1.7.10, Android 12, Android Studio Chipmunk

Part 2: Retrofit With Kotlin Coroutines

09. Use Kotlin Coroutines to Shorten API Calls

Episode complete

Play next episode

Next
About this episode

Leave a rating/review

See forum comments
Cinema mode Mark complete Download course materials
Previous episode: 08. Introduction Next episode: 10. Include Built-in Retrofit Support for Coroutines

Get immediate access to this and 4,000+ other videos and books.

Take your career further with a Kodeco Personal Plan. With unlimited access to over 40+ books and 4,000+ professional videos in a single subscription, it's simply the best investment you can make in your development career.

Learn more Already a subscriber? Sign in.

Transcript: 09. Use Kotlin Coroutines to Shorten API Calls

Just to show how easy implementing coroutines is, and how the code is more understandable than using callbacks, or some other mechanism, you’ll change the deleteTask API call, to rely on Coroutines. Let’s see how to do just that! :]

Demo

To start implementing coroutines, you need to add their dependency to the project. Open app level build.gradle. Then add the following dependencies to the project:

implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4'
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.5.1'

Sync the project, and you can get started! You’ll change the deleteTask call, to use coroutines, so head over to the RemoteApi.kt file.

Change the signature of the function, by using the Refactor -> Change Signature option and remove the lambda parameter, and change the return type to be a Result of the type String.

fun deleteTask(taskId: String): Result<String> {
}

The function will return the Result, instead of sending it through a callback. To achieve this behavior, you have to apply two small changes. You need to use a Coroutine builder, which returns a value from a coroutine, and makes it suspendable:

suspend fun deleteTask(taskId: String) = withContext(Dispatchers.IO) {

}

By adding the suspend modifier, you can use other suspend functions in the function, and you can suspend the coroutine. By using withContext, and the IO dispatcher, you tell the function to work in the background, and to return a value as the last statement in the block. Now, replace the callback-driven call with the following:

suspend fun deleteTask(taskId: String) = withContext(Dispatchers.IO) {
  try {
    val data = apiService.deleteNote(taskId).execute().body()

    if (data?.message == null) {
      Failure(NullPointerException("No response!"))
    } else {
      Success(data.message)
    }
  } catch (error: Throwable) {
    Failure(error)
  }
}

What you’re doing here is executing the request, in a try/catch block, in a background thread. You then take the body and return an appropriate result from both the try block and catch block. The code seems much simpler than with the callback, and is more natural to read! :] Now move to the TaskOptionsDialogFragment, and wrap the function call in a coroutine builder:

viewLifecycleOwner.lifecycleScope.launch {

}

Now change the code within, to the following:

val result = remoteApi.deleteTask(taskId)

if (result is Success) {
  taskOptionSelectedListener?.onTaskDeleted(taskId)
}
dismissAllowingStateLoss()

It’s nearly the same code, except that you don’t need a callback, you simply fetch the result from the API.

If you look at the code, it’s almost as if you don’t know coroutines are used, anyone can read the code, and understand enough to see what’s going on.

The main thread won’t be blocked, as the deleteTask is a suspend function. This means it will release the main thread for other work until the result is ready to be displayed. Pretty clever, right? :] Now run the project, and delete a note!

Well done! But if you think this is awesome and short and sweet, wait until you see how to use the built-in support for Coroutines, in Retrofit! :]