How to make HTTP calls on Android with Retrofit 2

Oleg Šelajev
6 min readJan 15, 2016

--

NB! Hey, the reviewed and more up to date version of this post is published on RebelLabs:

http://zeroturnaround.com/rebellabs/getting-started-with-retrofit-2/

You should rather read that one, than the text below. I have it in my todo list to update this version too, but I don’t know when I’ll have time to get to it.

I’ve recently become more and more interested in Android development and have been trying out different libraries that are supposed to be brilliant. More often than not they are really good. This is my first post in a series where I will produce a sample Android application that uses a combination of these amazing libraries so you can judge for yourself how good they are.

Today, I’ll look at using the Retrofit 2 HTTP client to see how complicated vs how beneficial it is for my application. Retrofit is one of the amazing tools that Square Inc. has released into the open source community. It’s a type-safe HTTP client, both for Android and Java applications.

The main premise behind type-safe HTTP clients is that you only need to worry about the semantics of the queries that you send over the network, rather than the details of how to construct URLs, specify parameters correctly and so forth. Retrofit makes this really easy by requiring you to write just a couple of interfaces, and that’s it!

Let’s see how it works on an example. The repository which I’ve added all my code to is available on Github, and as always, the best way to learn is to check it out and tinker with it yourself.

I started with an empty project in Android Studio. Personally, when welcomed with a choice of compatibility options and questions about which API I need to support in my application, I honestly get lost.

The good thing here, of course is that we’re just playing with a toy project, so we can boldly select the latest SDK and rush through the new project wizard to get ourselves a glorious, functioning “hello world” Android application.

Here’s the link to the commit if you don’t want to mess with the choices and rather just import the project from Github: Floating button app skeleton.

I always enable JRebel for Android for all projects. It’s packaged as an Android Studio plugin, so enabling it basically means that I click the custom button to run the app, everything else is taken care of. JRebel for Android is a productivity tool for Android developer that can instantly update code and resources on the running device or emulator. This essentially means that while you’re developing the application, you don’t have to waste the precious time waiting for your application to restart, often losing all the relevant application state on the way. Absolutely glorious!

Caveat, I work for ZeroTurnaround, the company that created JRebel for Android. However, that doesn’t make it any less useful, so you should check it out.

The new Android emulator that came with the Android Studio 2.0 is pretty snappy too. Now I see the screen with the MainActivity class active.

Clicking the floating button works and the snackbar comes up. All good, let’s verify that our infrastructure works fine by making a random code change to verify that the code reloading works. The first thing that comes to mind is to change the string value on the snackbar.

Lo and behold, one file save and one button click later we observe the reloaded code in action on the emulator. Now we’re unstoppable! And by that I mean we’re ready to investigate what Retrofit 2 has to offer.

Retrofit 2 is a type-safe HTTP client for Android (and Java), but first of all, it’s a library, so to use it we need to declare the correct dependencies. This is easy, however, note that we need to explicitly depend on the gson converter to transform the JSON responses to the model classes. It wasn’t the case with Retrofit 1, so be careful.

Add these two lines to the build.gradle file:

Now the main idea behind Retrofit is that it’s possible to generate the code to query HTTP services at runtime, requiring the developer to produce just an interface as the “specification”. Imagine we have a following model class:

From this we can create the GithubService interface that will embody our HTTP communication.

This is the simplest example, we add the @GET annotation on an interface method and provide the path part of the URL that we want to expose it on. Conveniently, the method parameters can be referenced in the path string so you won’t need to jump through hoops to set those. Additionally, with other annotations you can specify query parameters, POST request body and so on:

  • @Query(“key”) — for GET request query parameter
  • @QueryMap — for the map of parameters
  • @Body — use it with the @POST annotation to provide the query body content.

Now, to use this interface during runtime, we’ll need to build a Retrofit object:

I like to use the Retrofit builder in the same interface that contains the queries to the website. This way I’m not tempted to complicate things beyond measure. Yeah, there’s some general configuration in use here. We provide the default converter factory to turn the JSON response objects into Java objects, but it’s better to copy-paste that into every service you have rather than use a single abstraction only to find out it’s leaking.

With these pieces in place, we just need to perform the network call:

  • the specification of our queries
  • the Retrofit object builder

To create the implementation of the GitHubService interface, instantiate a Call object for the HTTP query which we want to perform and execute the request.

Alternatively, one might choose to schedule the call to happen asynchronously and provide the callback to be executed upon completion.

Sounds simple enough! Let’s prepare some sort of UI and wire the code in. Following the floating button app template design, we need to change the content_main.xml file. Here’s my take on adding a button to initiate the query and a text area to show the results:

Here’s how the network call code might look on your first try:

Naturally, this code won’t work, the Android framework won’t allow you to perform network calls on the UI thread. The UI thread should really only handle input from the user. Performing any long blocking operations on this thread will simply make the user experience sluggish.

So, we need to refactor this code by moving the the network call to a background thread. With JRebel for Android this won’t take is any time at all. Let’s extract the network call into an AsyncTask — the default framework to perform expensive computations on Android. AsyncTask is ugly and this particular implementation is not the cleanest, for example it creates Retrofit object every time we push the button, but it works.

And invoke that from the EventListener:

That’s it, the code now runs, the text view get’s updated with the result of out HTTP query.

The skeleton app is ready, the code builds and works. Now you are equipped to play with both Retrofit and JRebel for Android. You can change a line of code here and there and see the results of your new code in the running app, without any time-wasting. Try adding a couple of fields to the Contributor class. Replace the text view with a list of proper widgets for every contributor. Change the HTTP endpoint altogether and query another website. The world is your oyster.

In this post we looked at establishing a minimal skeleton app that uses Retrofit 2 for network calls. The code is available on Github. The best way to utilize this post is to clone the app, import it into Android studio and play with the code yourself using this post as a quick introduction to the relevant areas to focus on.

In the future, I hope I’ll expand on this skeleton app, adding some sort of dependency injection framework to avoid messing with the UI code, throw in a bit of RxAndroid to process the network queries reactively, and so on. By the way, what are your default goto libraries, that you use in any Android project? Maybe it’ll be interesting to look at those instead. Ping me on Twitter: @shelajev, I’d be happy to chat!

--

--