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). GET, POST, PUT, PATCH, 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
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.
2. Declaring Dependencies
After creating a new project, declare the following dependencies in your build.gradle. The 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.
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.
Then click the Preview button to generate the Java objects.
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 GET, POST, PUT, 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.
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
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.
Android
Getting Started With ReactiveX on Android
Ashraff Hathibelagal
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 POST, PUT, 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.
Communication Within an Android App With EventBus
Greenrobot EventBus is a popular open-source library that uses the publish/subscribe model for communication between components of the Android system. In...
Chike Mgbemena
25 Nov 2016
Android
Practical Concurrency on Android With HaMeR
In this tutorial we’ll explore the HaMeR (Handler, Message and Runnable) framework, one of the most powerful concurrency models available on Android. With a...
Tin Megali
19 Sep 2016
Android SDK
Android From Scratch: Using REST APIs
In this tutorial, I'm going to show you how to use the classes and methods available in the Android SDK to connect to remote web servers and interact with...
Ashraff Hathibelagal
05 Sep 2016
Android SDK
Get Started With an Android App Template in 60 Seconds
CodeCanyon has hundreds of Android app templates that you can use to jump start your development. This video will show you how to install and customize a...
Ashraff Hathibelagal
07 Oct 2016
Android SDK