Retrofit 2 — Introduction to Call Adapters

It's time to kick off a brand-new Retrofit topic and mini series: call adapters. In this first introductory tutorial you'll learn what call adapters are and how you can utilize them in Retrofit.

Retrofit Series Overview

Call Adapter Basics — What Are They?

Before we can dive into call adapters, we need to go into the details of how Retrofit works. Retrofit uses an HTTP client (OkHttp) to execute the network requests. This execution happens on a background thread.

When OkHttp client receives a response from the server, it passes the response back to Retrofit. Retrofit then does its magic: it pushes the meaningless response bytes through converters and wraps it into a usable response with meaningful Java objects. This resource-intensive process is still done on a background thread. Finally, when everything is ready Retrofit needs to return the result to the UI thread of your Android app.

By default, this return wrapping is done as Call<TypedResponseClass>type. This action of returning from the background thread, which receives and prepares the result, to the Android UI thread is a call adapter!

Basically, call adapters are sitting on top of Retrofit and offer the functionality to you as the developer. The call adapter of your choice decides how you interact with the Retrofit core. You've to understand that call adapters are in charge of controlling the management, execution and response handling of Retrofit. This might sound quite vague, but it'll become clear when you read on and see some examples.

Being able to change call adapters means you can completely change your app's Retrofit logic. Essentially, there are three approaches to call adapters:

  • Keep the default Call<TypedResponseClass> call adapter
  • Integrate and use a pre-built call adapter that tie in Retrofit with an existing flow or logic framework
  • Create a custom-build call adapter specifically implemented for your use case

Because we use the first option in the majority of our tutorials, we'll skip it in this introduction and focus on the latter two.

Integrate Pre-built Call Adapters

As mentioned above, there are pre-build call adapters. We differentiate between two kinds: first-party and third-party call adapters.

First-Party Call Adapters

The developers of Retrofit provide multiple call adapters for common frameworks. At the time of writing this tutorial it is RxJava, RxJava 2, Guava, Java 8. You can add them as a dependency via Gradle:

dependencies {  
    // Retrofit
    compile 'com.squareup.retrofit2:retrofit:2.5.0'

    // For example, add call adapter for RxJava 2
    compile 'com.squareup.retrofit2:adapter-rxjava2:2.5.0'

    // or alternatively:
    compile 'com.squareup.retrofit2:adapter-rxjava:2.5.0'
    compile 'com.squareup.retrofit2:adapter-guava:2.5.0'
    compile 'com.squareup.retrofit2:adapter-java8:2.5.0'
}

Retrofit Instance

After syncing your project you can access the call adapter's code. However, this isn't enough. In order to let Retrofit know that it shouldn't wrap responses in the default Call<> anymore and instead use, for example, RxJava 2's Observable<>, you need to change your Retrofit declaration:

Retrofit retrofit =  
  new Retrofit.Builder()
      .baseUrl(apiBaseUrl)
      .addConverterFactory(GsonConverterFactory.create())
      .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
    .build();

In the snippet above we've added the addCallAdapterFactory(RxJavaCallAdapterFactory.create()) method call. Consequently, this Retrofit instance can now also wrap the responses in RxJava types. However, the preparation isn't completely done yet.

Interface Declaration

Of course, you'll also need to update your interface declaration. The return type of the method needs to be updated to reflect the new RxJava type:

public interface GistService {  
    // OLD standard call adapter type
    @GET("gists")
    Call<List<Gist>> getGists();

    // NEW RxJava call adapter type
    @GET("gists")
    Observable<List<Gist>> getGists();
}

Multiple Call Adapters

It's important to note that you don't need to change your entire app over to one exclusive call adapter, because you can mix them! Use the call adapter that fits your method and scenario, even if it means you use two (or more!) different call adapters within your app. This is explicitly supported:

public interface GistService {  
    // access Gists with default call adapter
    @GET("gists") 
    Call<List<Gist>> getGists();

    // create new Gist with RxJava call adapter
    @POST("gists")
    Observable<ResponseBody> createGist(@Body Gist gist);
}

Even with this mixed declaration you can use the single Retrofit instance from above. If you need even more call adapters, you can also add them to the Retrofit instance with another addCallAdapterFactory() call. Similar to Retrofit's converter management, Retrofit will manage all of them and pick the call adapter that fits the method.

This would be all you need to set up your app for the RxJava call adapter. Of course, we only showed you one out of the four first-party call adapters, but the others principally work the same. We'll take a closer look at each of them in dedicated future tutorials.

Call adapters are not just limited to these four, you should be aware that there are other call adapters as well.

Third-Party Adapters

Of course, you can always write an call adapter for your logic framework, if you don't use RxJava or one of the others. At the time of writing, call adapters for Bolts and Agera are published and supported by third-party developers.

Custom Adapters

Finally, and for us the most interesting call adapters: custom ones. Call adapters can be powerful and clean solutions to messy problems. You'll learn how to implement your custom call adapters in upcoming tutorials. A variety of sample usages will demonstrate how efficient call adapters can be. For example, Retrofit's two default callbacks (onResponse and onFailure) are not very convenient. In the next tutorials you'll learn to setup your own callback mechanism!

Summary

In this tutorial you've seen an introduction into Retrofit call adapters. You've learned what their purpose is and how you can add one of the first-party call adapters. You are now also aware that there are third-party and custom call adapters as well. Of course, this was only the beginning and we'll start with the fun stuff in the next tutorial.

Do you have further questions on this topic or about Retrofit in general? Just let us know on Twitter @futurestud_io or leave a comment below.

Enjoy coding & make it rock!

Explore the Library

Find interesting tutorials and solutions for your problems.