Safe Retrofit calls extension with kotlin Coroutines for Android in 2021 — Part II
Hello again 👋, this is the second part of the series. If you haven’t read the first part, I encourage you to do it in order to understand all the things we are going to do now.
Now that we know how do we have to handle exceptions with coroutines, lets code.
1. Set up or project ⚒️
We gonna use Retrofit and coroutines for this, therefore we are going to add the following dependencies to our app (or android/kotlin library) module gradle file
dependencies { // Current versions at the time
def retrofit_version = "2.9.0"
def coroutines_version = "1.5.0"
implementation "com.squareup.retrofit2:retrofit:$retrofit_version" implementation "com.squareup.retrofit2:converter-moshi:$retrofit_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version"}
2. Parse exceptions ♻️
There are some common exceptions that could happen when executing a network call, such as SocketTimeoutException
, SSLHandshakeException
, HttpException
, etc. but we are not going to send those exceptions directly, instead of that, we are going to transform those exceptions into readable failures! Let’s do it!
First we are going to create or custom failures extending them from the Failure class.
Now that we got our custom failures, it’s time to map the exceptions into them.
ResponseError
class is just a structure that represents a handled backend failure, something like a 4XX error.3. Make retrofit call execution thread safe ⛑️
Now that we have our exception parser extension function we can use it to catch and parse any exception that could happen while executing a network call.
So the above suspend function has some key features that i’m going to explain to you.
- ioDispatcher — Coroutine Dispatcher which is expected to be a IO Dispatcher for your app and a TestCoroutineDispatcher in your unit tests.
- adapter — It accepts a JsonAdapter<ResponseError> which an adapter for parse a JSON object into the desired ResponseError data class
- retrofitCall — A crossinline suspend function that will be the one who takes your service and execute it safety inside the
withContext
block. If you don’t have experience with inline functions see the following video where Florina Muntenescu explains it - toSuccess() & toError() — These are just extension functions that wraps any object into a Either.Success or Either.Error instance.
4. Integrate it all 🧩
Ok, that’s it. You have a safe retrofit call wrapper extension function! And you can use it just like this
The last part where I use the .let {…}
it’s just because the actorsService.getActors()
returns a ResponseItems<ActorResponse>
object. I just use the Either.mapSuccess
helper method for extract the result and return a List of ActorsResponse as expected.
So that what’s it… is it? Uhm… kind of. We could add a little bit of customization here by adding a middleware layer! What can a middleware do for us? It could probably check that the cellphone is connected to the internet or you could validate some data, etc.
Let’s implement a middleware for fun. 👉 Go to part 3 for learn how to do it!
Sample project 👇
See you soon 👋