Chapters

Hide chapters

Kotlin Coroutines by Tutorials

Third Edition · Android 12 · Kotlin 1.6 · Android Studio Bumblebee

Section I: Introduction to Coroutines

Section 1: 9 chapters
Show chapters Hide chapters

16. Networking With Coroutines
Written by Luka Kordić

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

Almost every Android app today has some form of network communication. User management, like login and registration, fetching news feed from your backend and uploading a profile picture are just a few of the most common tasks that require you to write networking code. That said, it’s important to keep your UI thread free to do other work while your app communicates with the server. Because networking code is quite common in Android apps, you want to make sure it is:

  • Performant - not blocking the main thread
  • Easy to read
  • Maintainable
  • Testable

In this chapter, you’ll see several ways of doing network calls via Retrofit library. First, you’ll make the standard API call with the callback-style approach and Retrofit’s Call as a return type. Then, you’ll replace that with a much more readable and shorter approach - using the power of coroutines and suspend functions.

Getting Started

For this chapter, you’ll use the same Disney API from previous chapters to obtain a list of characters and present it to the user. To start, open the starter project for this chapter and inspect the code. Focus on the following files:

  • DisneyApi.kt in data/networking package
  • DisneyApiService.kt in data/networking package
  • DisneyActivity.kt in ui/activity package

DisneyApi.kt is the interface to use when creating Retrofit instance. DisneyApiService.kt contains the implementation of the API calls defined in the interface. DisneyActivity.kt represents a simple screen with the basic RecyclerView setup for displaying a list of Disney characters.

Network Call With Callbacks

To check out the callback-style based implementation, start with DisneyApi.kt file. You’re going to use getCharacters, which looks like this:

@GET("characters")
fun getCharacters(): Call<CharactersResponse>
fun getCharacters(
  onError: (Throwable) -> Unit,
  onSuccess: (List<DisneyCharacter>) -> Unit
  ) {
  // Make an asynchronous request
  disneyApi.getCharacters().enqueue(object : Callback<CharactersResponse> {
    override fun onResponse(
      call: Call<CharactersResponse>,
      response: Response<CharactersResponse>
    ) {
      // Invoke onSuccess lambda when the results are ready
      val data = response.body()
      if (data == null) {
        onError(Throwable("No response"))
      } else {
        onSuccess(data.data)
      }
    }

    override fun onFailure(call: Call<CharactersResponse>, t: Throwable) {
      // Invoke onError if an error happens
      onError(t)
    }
  })
}

Coroutine-Powered Networking

To see how easy it is to implement coroutines for networking, and how it makes the code more understandable compared with callbacks or other mechanisms, you’re going to refactor the previous example to rely on coroutines. Go back to your DisneyApiService.kt and replace the getCharacters implementation with this one:

// 1
suspend fun getCharacters(): Result<CharactersResponse> = withContext(Dispatchers.IO) {
  try {
    // 2
    val data = disneyApi.getCharacters().execute().body()
    // 3
    if (data == null) {
      Result.failure(Throwable("No response"))
    } else {
      Result.success(data)
    }
  } catch (error: Throwable) {
    // 4 
    Result.failure(error)
  }
}
private fun fetchDisneyCharacters() {
    lifecycleScope.launch {
      apiService.getCharacters()
        .onSuccess { showResults(it.data) }
        .onFailure { showError(it) }
    }
  }

Retrofit Meets Coroutines

Here’s a quick recap of what you had to do to switch your API call to use coroutines:

@GET("characters?page=2")
suspend fun getCharactersSuspend(): CharactersResponse
suspend fun getCharacters(): Result<CharactersResponse> = kotlin.runCatching {
  disneyApi.getCharactersSuspend()
}

Key Points

  • Prefer Kotlin Coroutines over callback-style approach to make your networking code simple and more readable.
  • Mark your Retrofit methods with suspend and return the data model you need.
  • Retrofit will do the threading for you when you use suspend.
  • Make sure to catch any potential errors in the networking layer of the app.
  • If you need some metadata about the response, use Retrofit’s Response<T> as a return type.

Where to Go From Here?

That’s it for this chapter. It’s a short one, but that’s only because coroutines make networking on Android short and sweet! :]

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.
© 2024 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