Kotlin Coroutines and Retrofit

Understanding a bit of Kotlin Coroutines and making them work for your Android application networking shenanigans.

It’s been a while since I last blogged about Android in general and so much has changed since my last article on Retrofit that I published about 2 years ago. If you’re an absolute beginner then it’s a must-read, you’ll probably love it ;). Ehem,

And Java was beautiful :’(

Okay, so maybe it wasn’t as beautiful but you have to admit that Java did a great job during its tenure as Android’s main development language.

Kotlin and now coroutines have now made networking on Android even easier than ever before!

Kotlin Coroutines: A brief intro.

Coroutines are a neat new feature of the Kotlin language that allow us to write asynchronous code in a more idiomatic way. — This also means you can write asynchronous code the same way you would normally write synchronous code in your project.

In order to do asynchronous programming you may have had to use Async Tasks, Threads (which may have been blocking, meh), Callbacks or even RxJava. Using callbacks could have easily ran you into something known as Callback Hell” — Shoutout to all the JS programmers who’ll read this. And with RxJava, from experience, I noticed that there was quite the learning curve in-order to get an understanding of how to use the various combinators in the case of chaining a few asynchronous calls.

According to the Kotlin docs it is stated that coroutines are a lightweight alternative to threads.

“Coroutines provide a way to avoid blocking a thread and replace it with a cheaper and more controllable operation”

Coroutines in your Android Project

Kotlin coroutines in Android are very simple to enable in your project. Since they are still in an experimental mode, you may need to also include a few extra steps in your application level build.gradle file.

To begin add the following library to your build.gradle file dependencies:

dependencies {
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.0.1'
.........
}

Update Note: You’ll also need to be on kotlin version 1.3 or better.

That’s really all there is to it folks!!

Launching a Coroutine.

As mentioned earlier. A coroutine is just a lightweight thread. The folks at Jetbrains created suspending functions which are basically just normal Kotlin functions with the modifier suspend indicating that the function can suspend the execution of a coroutine.

“Suspending functions can take parameters and return values in the same manner as regular functions, but they can only be called from coroutines and other suspending functions, as well as function literals inlined into those.”

I have included code snippet of a coroutine in action is as below:

class MainActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)


CoroutineScope.launch (Dispatchers.Main){
toast("Hello it has started")
delay(10,TimeUnit.SECONDS)
textView.text = "I have changed after 10 seconds"
}
}
}

As you can see above we used coroutine builders in order to launch and execute a coroutine from a scope which was non-suspending. Easy right!?

Breaking down coroutine builders:

  • launch — This builder simply launches a new coroutine and returns a reference to it as a Job object which does not have a result. If you intend to block the current thread, instead of launch you may use runBlocking builder instead.
  • async — This builder launches new coroutine and returns a reference to it as a Deferred type object which may have a result. It is usually used along with await which is a suspending function which can wait for a result without blocking the current thread.

And Dispatchers.Main — this isn’t a coroutine builder however we pass it into our launch builder in order to notify the Android system that we will need to update the UI thread at some point during our coroutine execution.

At the time of writing this article the kotlinx.coroutine docs state that standalone builders have been deprecated.

There is so much more interesting and awesome things about coroutines but I’ve decided to keep it simple and move to the part you may have been waiting for ……. Drum Roll ………

Making it work with Retrofit?

Okay so Retrofit is a type-safe HTTP client for Android and Java.

In-order to make it work with coroutines there is a Call Adapter created by Jake Wharton which uses Kotlin coroutine’s Deferred type if you're using a Retrofit version behind 2.6.0.

Starting from Retrofit 2.6.0 you no longer require the Call Adapter as Retrofit now includes built-in support for Kotlin suspend modifier on functions.

In order to begin, let’s add the following lines into our app level build.gradle file:

dependencies {
//.................
//.................
implementation 'com.squareup.retrofit2:retrofit:2.6.0'
implementation 'com.squareup.retrofit2:converter-moshi:2.6.0'
}

I know this should go without saying however never forget to include the internet permission inside the AndroidManifest.xml file within your project.

Declaring our interface.

For this quick example I used an API from JSONPlaceholder for demonstration.

Observe the below snippet for our interface:

interface RetrofitService {
@GET("/posts")
suspend fun getPosts(): Response<List<Post>>
}

You may notice that instead of Call<T>, we now have a function with the suspend modifier defined in our interface function.

According to Retrofit documentation this function will, behind the scenes behave as a normal Call.enqueue operation.

Also we wrap our response in a Response object to get metadata about our request response e.g. information like response code.

We no longer have to await() anymore as this is handled automatically! As with all networking on Android its done on the background. And this is a very clean way of doing so!

Building our Retrofit Service.

Updated: our Retrofit instance will look like the following code snippet:

object RetrofitFactory {
const val BASE_URL = "https://jsonplaceholder.typicode.com"

fun makeRetrofitService(): RetrofitService {
return Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(MoshiConverterFactory.create())
.build().create(RetrofitService::class.java)
}
}

Bringing it all together into action.

Making the request via coroutines is now as simple as (Updated) :

class MainActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

val service = RetrofitFactory.makeRetrofitService()
CoroutineScope(Dispatchers.IO).launch {
val response = service.getPosts()
withContext(Dispatchers.Main) {
try {
if (response.isSuccessful) {
//Do something with response e.g show to the UI.
} else {
toast("Error: ${response.code()}")
}
} catch (e: HttpException) {
toast("Exception ${e.message}")
} catch (e: Throwable) {
toast("Ooops: Something else went wrong")
}
}
}
}
}

Boom! — Its waayyy cleaner and easier to debug.

To explain a bit calling the suspended function getPosts() pretty much allowed the function to wait for a result before processing the if else condition within the main or UI thread.

Compared to how we used to deal with Call objects in Retrofit before I’d say networking just got a whole lot easier.

Update: These features are no longer experimental, so feel free to use them in your production project. I personally believe Kotlin Coroutines could replace your RxJava implementation when it comes to networking. Go on! Give it a spin and tell me what you think!

That is all for now!

That’s all folks.

Side note: I updated the blog to work with the non-experimental Kotlin Coroutines, this means that the code snippets found in this blog post will now only work with Kotlin version 1.3 or better.

Also some people in the comments pointed out to me that my example was not exception handling. I updated my code snippet to reflect this as well.

Thanks to Lou Morda and Roar Grønmo for their comments which allowed me to update this article with a more efficient solution. I have also updated the sample repository on Github with the changes.

If anything is still unclear I added a repository with the sample application to aide you as you explore the exciting world of Kotlin Coroutines in your networking.

Thank you for giving this article a read. Please clap and share if you found this helpful. Also leave a comment if you’d like me to explore coroutines in depth as well as more tips and tricks to use them along with Retrofit.

Oh by the way, here are some helpful links to help you with understanding Kotlin Coroutines:

Until next time — Live long and prosper — By next time I mean I will have another article in about 2 weeks :D.

Android application developer,Web apps developer , UX Design and Material Design Enthusiast.