Loading...
Home
  • Tech Blogs
  • Videos
  • Conferences
    • Droidcon News
    • Upcoming Conferences
    • Become a Partner
    • Past Events
    • Keep Me Informed
    • Diversity Scholarships
  • Community
    • droidcon Team
    • How to Hold a Droidcon
  • Android Careers
Sign In

Global CSS

 

Retrofit CallAdapter for Either type

 

 
Lukasz Kalnik
Published: July 16, 2020
Tweet
Share
 

Image by Ich bin dann mal raus hier. from Pixabay

 

The Arrow.kt Either type is very practical for handling domain errors in the app.

What if we could get the type returned directly from our REST API calls made with Retrofit and use it consistently in the whole application?

Retrofit gives us two kinds of errors:

  1. Http errors, i.e. responses with Http codes 4xx-5xx (client/server errors). They are returned in the same onResponse() callback as successful responses (with codes 2xx). They can be distinguished from each other by checking Response.isSuccessful() .
  2. Network errors (network not available etc.) which are returned in the onFailure() callback as IOExceptions.

To make Retrofit use a custom Callback<T> converting the possible success/error cases to the Either type we need to wrap the callback in a CallAdapter and pass Retrofit a CallAdapterFactory capable of returning this adapter. Let’s see how we can do it.


First, let’s create a sealed class hierarchy of possible error cases.

 

 

HttpError will contain the error code (4xx-5xx) and body of a possible Http error response.

NetworkError will contain possible IOException in case of lack of connectivity and similar errors.

UnknownApiError is for all unexpected types of errors.


Our example Retrofit API is using coroutines. It is defined using suspendfunctions returning the anticipated Either type.

 

 

The first Either type argument is always our ApiError sealed hierarchy, the second type argument is the expected domain type (by convention in Either error is associated with the left side and success with the right).

When our Retrofit API is defined using suspend functions, under the hood Retrofit is wrapping our API calls in its Call<T> type. See how it is implemented in Retrofit Kotlin extensions.

Because of that, our CallAdapter will have to convert the original Call to our special EitherCall which does all the wrapping in the Either type.

You can find the ready implementation in my example Moovis project. Let’s go through it step by step.


First, we need to create the EitherCall class extending Call with the type argument Either<ApiError, R>. It will take the original call as delegateand delegate all the standard work to it which we don’t want to customize. It will also take the expected successType to check if it is a Unit (this is useful for responses like 204 No content).

The only non-trivial method we are implementing is enqueue() . There we pass our callback implementing the onResponse() and onFailure()methods.

Note that the data is wrapped into a synthetic Response.success() call. This is the only way to return success/failure cases consistently in the same Either data type from Retrofit. Also note that all the onResponse() logic of checking if response is successful, if it had a body etc. is moved to a private extension function Response.toEither().

The onFailure() callback just checks if the error is an IOException (i.e. a network problem on the client) or an unknown error.

 

 


This was already actually the hardest part of our work!

The next step is to create an EitherCallAdapter extending CallAdapter. It has our successType as property and only implements two methods: adapt() which wraps the original Call into our EitherCall and responseType() which simply returns the passed successType.

 

 


In order to pass the newly created EitherCallAdapter to your Retrofit instance, you need to create an EitherCallAdapterFactory extending CallAdapter.Factory. There the overridden get() method performs several checks and returns null if it thinks the expected return type is not compatible with our EitherCallAdapter or otherwise an adapter instance with the expected success type.

 

 

As you see above, first the raw return type is checked if it is a Call and also if it is a parameterized (generic) type.

If yes, its type parameter upper bound on position 0 has to be Either and it also has to be parameterized.

Again we check Either type parameter upper bound on position 0 (left type). It has to be ApiError (we only support this type).

The type on position 1 is the rightType which we pass to EitherCallAdapter as the expected successType.


The last step is passing the EitherCallAdapterFactory to your Retrofit instance.

 

 

You can now call your API methods like this out of the box:

 

 

Like mentioned above, the whole example implementation you can find in my sample Moovis project.

 

 

 

Tags: Android, Retrofit, Either

 

View original article at: 


 

Originally published: June 18, 2020

Android News
Evolution of Android Update SystemEvolution of Android Update System
Evolution of Android Update SystemEvolution of Android Update System

By Ivan Kuten

So, how can you update Android on mobile devices? While developing software for Smart TVs and Android-based set-top boxes, we’ve narrowed it down to four ways, discarding some very exotic options:

By ProAndroidDev -
Android News
Happy Railway
Happy Railway

By Hadi Lashkari Ghouchani

This post is on the tail of Railway Oriented Programming in Kotlin by Antony Harfield. So you need to read it first and continue here. As it’s obvious I really liked it and tried it out. It needs every process have a result like

By ProAndroidDev -
Android News
Unit Tests and Concurrency
Unit Tests and Concurrency

By Stojan Anastasov

Once Retrofit added RxJava support, RxJava became my go-to concurrency framework for writing Android apps. One of the great things about RxJava is the excellent testing support. It includes TestObserver, TestScheduler, RxJavaPlugins so you can switch your schedulers in tests.

By ProAndroidDev -
Android News
When Compat libraries will not save you
When Compat libraries will not save you

By Danny Preussler

And why you should avoid using the “NewApi” suppression! The idea of “Compat” libraries was probably one of the key aspects of Android dominating the mobile space. Other than with iOS, Android users often could not update their operating system after a new version launch, simply as their phones won’t allow them to, the Android problem of fragmentation.

 

By ProAndroidDev -
droidcon News

Tech Showcases,

Developer Resources &

Partners

/portal/rest/jcr/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/home-details/EmployerBrandingHeader
EmployerBrandingHeader
https://jobs.droidcon.com/
/portal/rest/jcr/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/employerbranding/jobs-droidcon/jobs.droidcon.com
jobs.droidcon.com

Latest Android Jobs

http://www.kotlinweekly.net/
/portal/rest/jcr/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/employerbranding/kotlin-weekly/Kotlin Weekly
Kotlin Weekly

Your weekly dose of Kotlin

https://proandroiddev.com/
/portal/rest/jcr/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/employerbranding/pad/ProAndroidDev
ProAndroidDev

Android Tech Blogs, Case Studies and Step-by-Step Coding

/detail?content-id=/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/employerbranding/Zalando/Zalando
/portal/rest/jcr/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/employerbranding/Zalando/Zalando
Zalando

Meet one of Berlin's top employers

/detail?content-id=/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/employerbranding/Academy for App Success/Academy for App Success
/portal/rest/jcr/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/employerbranding/Academy for App Success/Academy for App Success
Academy for App Success

Google Play resources tailored for the global droidcon community

Follow us

Team droidcon

Get in touch with us

Write us an Email

 

 

Quicklinks

> Code of Conduct

> Terms and Conditions

> How to hold a conference

> FAQs

> Imprint

Droidcon is a registered trademark of Mobile Seasons GmbH Copyright © 2020. All rights reserved.

powered by Breakpoint One