Get Started With Retrofit 2 HTTP Client

Final product image
What You'll Be Creating

What Is Retrofit?

Retrofit is a type-safe HTTP client for Android and Java. Retrofit makes it easy to connect to a REST web service by translating the API into Java interfaces. In this tutorial, I'll show you how to use one of most popular and often-recommended HTTP libraries available for Android. 

This powerful library makes it easy to consume JSON or XML data which is then parsed into Plain Old Java Objects (POJOs). GETPOSTPUTPATCH, and DELETE requests can all be executed. 

Like most open-source software, Retrofit was built on top of some other powerful libraries and tools. Behind the scenes, Retrofit makes use of OkHttp (from the same developer) to handle network requests. Also, Retrofit does not have a built-in any JSON converter to parse from JSON to Java objects. Instead it ships support for the following JSON converter libraries to handle that: 

  • Gson: com.squareup.retrofit:converter-gson
  • Jackson: com.squareup.retrofit:converter-jackson
  • Moshi: com.squareup.retrofit:converter-moshi

For Protocol Buffers, Retrofit supports:

  • Protobuf: com.squareup.retrofit2:converter-protobuf
  • Wire: com.squareup.retrofit2:converter-wire

And for XML, Retrofit supports:

  • Simple Framework: com.squareup.retrofit2:converter-simpleframework

So Why Use Retrofit?

Developing your own type-safe HTTP library to interface with a REST API can be a real pain: you have to handle many functionalities such as making connections, caching, retrying failed requests, threading, response parsing, error handling, and more. Retrofit, on the other hand, is very well planned, documented, and tested—a battle-tested library that will save you a lot of precious time and headaches.

In this tutorial, I will explain how to use Retrofit 2 to handle network requests by building a simple app to query recent answers from the Stack Exchange API. We'll perform GET requests by specifying an endpoint—/answers, appended to the base URL https://api.stackexchange.com/2.2/—then get the results and display them in a recycler view. I will also show you how to do this with RxJava for easy management of the flow of state and data.

1. Create an Android Studio Project

Fire up Android Studio and create a new project with an empty activity called MainActivity.

Create a new empty activity

2. Declaring Dependencies

After creating a new project, declare the following dependencies in your build.gradleThe dependencies include a recycler view, the Retrofit library, and also Google's Gson library to convert JSON to POJO (Plain Old Java Objects) as well as Retrofit's Gson integration. 

Don't forget to sync the project to download these libraries. 

3. Adding Internet Permission

To perform network operations, we need to include the INTERNET permission in the application manifest: AndroidManifest.xml.

4. Generating Models Automatically

We are going to create our models automatically from our JSON response data by leveraging a very useful tool: jsonschema2pojo

Get the Sample JSON Data

Copy and paste https://api.stackexchange.com/2.2/answers?order=desc&sort=activity&site=stackoverflow in your browser's address bar (or you could use Postman if you are familiar with that tool). Then press Enter—this will execute a GET request on the given endpoint. What you will see in response is an array of JSON objects. The screenshot below is the JSON response using Postman.

API response to GET request

Copy this JSON response either from your browser or Postman. 

Map the JSON Data to Java

Now visit  jsonschema2pojo and paste the JSON response into the input box.

Select a source type of JSON, annotation style of Gson, and uncheck Allow additional properties

jsonschema2pojo interface

Then click the Preview button to generate the Java objects. 

jsonschema2pojo output

You might be wondering what the @SerializedName and @Expose annotations do in this generated code. Don't worry, I'll explain it all!

The @SerializedName annotation is needed for Gson to map the JSON keys with our fields. In keeping with Java's camelCase naming convention for class member properties, it is not recommended to use underscores to separate words in a variable. @SerializedName helps translate between the two.

In the example above, we are telling Gson that our JSON key quota_remaining should be mapped to the Java field quotaRemaining.  If both of these values were the same, i.e. if our JSON key was quotaRemaining just like the Java field, then there would be no need for the @SerializedName annotation on the field because Gson would map them automatically.

The @Expose annotation indicates that this member should be exposed for JSON serialization or deserialization. 

Import Data Models to Android Studio

Now let's go back to Android Studio. Create a new sub-package inside the main package and name it data. Inside the newly created data package, create another package and name it model. Inside the model package, create a new Java class and name it Owner. Now copy the Owner class that was generated by jsonschema2pojo and paste it inside the Owner class you created. 

Do the same thing for a new Item class, copied from jsonschema2pojo. 

Finally, create a class named SOAnswersResponse for the returned StackOverflow answers. You'll find the code for this class in jsonschema2pojo as Example. Make sure you update the class name to SOAnswersResponse wherever it occurs. 

5. Creating the Retrofit Instance

To issue network requests to a REST API with Retrofit, we need to create an instance using the Retrofit.Builder class and configure it with a base URL. 

Create a new sub-package package inside the data package and name it remote. Now inside remote, create a Java class and name it RetrofitClient. This class will create a singleton of Retrofit. Retrofit needs a base URL to build its instance, so we will pass a URL when calling RetrofitClient.getClient(String baseUrl). This URL will then be used to build the instance in line 13. We are also specifying the JSON converter we need (Gson) in line 14. 

6. Creating the API Interface

Inside the remote package, create an interface and call it SOService. This interface contains methods we are going to use to execute HTTP requests such as GETPOSTPUT, PATCH, and DELETE. For this tutorial, we are going to execute a GET request. 

The @GET annotation explicitly defines that GET request which will be executed once the method gets called. Every method in this interface must have an HTTP annotation that provides the request method and relative URL. There are five built-in annotations available: @GET@POST, @PUT@DELETE, and @HEAD.

In the second method definition, we added a query parameter for us to filter the data from the server. Retrofit has the @Query("key") annotation to use instead of hard-coding it in the endpoint. The key value represents the parameter name in the URL. It will be added to the URL by Retrofit. For example, if we pass the value "android" as an argument to the getAnswers(String tags) method, the full URL will be:

Parameters of the interface methods can have the following annotations:

@Path variable substitution for the API endpoint
@Query specifies the query key name with the value of the annotated parameter
@Body payload for the POST call 
@Header specifies the header with the value of the annotated parameter

7. Creating the API Utils

Now are going to create a utility class. We'll name it ApiUtils. This class will have the base URL as a static variable and also provide the SOService interface to our application through the getSOService() static method.

8. Display to a RecyclerView

Since the results will be displayed in a recycler view, we need an adapter. The following code snippet shows the AnswersAdapter class.

9. Executing the Request

Inside the onCreate() method of the MainActivity, we initialize an instance of the SOService interface (line 9), the recycler view, and also the adapter. Finally, we call the loadAnswers() method. 

The loadAnswers() method makes a network request by calling enqueue(). When the response comes back, Retrofit helps us to parse the JSON response to a list of Java objects. (This is made possible by using GsonConverter.)  

10. Understanding enqueue()

enqueue() asynchronously sends the request and notifies your app with a callback when a response comes back. Since this request is asynchronous, Retrofit handles it on a background thread so that the main UI thread isn't blocked or interfered with.

To use enqueue(), you have to implement two callback methods:

  • onResponse()
  • onFailure()

Only one of these methods will be called in response to a given request. 

  • onResponse(): invoked for a received HTTP response. This method is called for a response that can be correctly handled even if the server returns an error message. So if you get a status code of 404 or 500, this method will still be called. To get the status code in order for you to handle situations based on them, you can use the method response.code(). You can also use the isSuccessful() method to find out if the status code is in the range 200-300, indicating success.
  • onFailure(): invoked when a network exception occurred communicating to the server or when an unexpected exception occurred handling the request or processing the response. 

To perform a synchronous request, you can use the execute() method. Be aware that synchronous methods on the main/UI thread will block any user action. So don't execute synchronous methods on Android's main/UI thread! Instead, run them on a background thread.

11. Testing the App

You can now run the app. 

Sample results from StackOverflow

12. RxJava Integration

If you are a fan of RxJava, you can easily implement Retrofit with RxJava. In Retrofit 1 it was integrated by default, but in Retrofit 2 you need to include some extra dependencies. Retrofit ships with a default adapter for executing Call instances. So you can change Retrofit's execution mechanism to include RxJava by including the RxJava CallAdapter

Step 1

Add the dependencies.

Step 2

Add the new CallAdapter RxJavaCallAdapterFactory.create() when building a Retrofit instance.  

Step 3

Now, update the getAnswers()  methods to return Observables:

Step 4

When making the requests, our anonymous subscriber responds to the observable's stream which emits events, in our case SOAnswersResponse. The onNext method is then called when our subscriber receives any event emitted which is then passed to our adapter. 

Check out Getting Started With ReactiveX on Android by Ashraff Hathibelagal to learn more about RxJava and RxAndroid. 

Conclusion

In this tutorial, you learned about Retrofit: why you should use it and how. I also explained how to add RxJava integration with Retrofit. In my next post, I'll show you how to perform POSTPUT, and DELETE, how to send Form-Urlencoded data, and how to cancel requests. 

To learn more about Retrofit, do refer to the official documentation. And in the meantime, check out some of our other courses and tutorials on Android app development.

Tags:

Comments

Related Articles