What is Retrofit, exactly?
Retrofit is a powerful and popular library for Android and Java, developed by Square, the minds behind Dagger, Moshi, OKHTTP, etc. It is a type-safe library designed to simplify the process of sending network requests using OKHTTP to fetch data from API’s using the RESTful architectural style. This library makes fetching JSON or XML data from an REST API fairly straightforward. Once the data is retrieved, it is then parsed into a Plain Old Java Object (POJO), which must be defined for each "resource" in the response.
Why use Retrofit?
Writing/maintaining networking code by hand, although doable, can be a real pain. You have to handle many aspects, such as making connections, caching, retrying failed requests, threading, response parsing, error handling, and more. Retrofit, on the other hand, is a well-planned, documented and tested library that will save you a lot of your development time, headaches and keep your code in a developer friendly fashion. There is no point in reinventing the wheel, especially in software development.
In order to get some performance benchmarking, we pitted Retrofit against another networking library, Volley and used them to run several API calls. The results speak for themselves.
In all of the above tests with varying repeats, Volley was anywhere from 50% to 75% faster than AsyncTasks. Retrofit clocked in at an impressive 50% to 90% faster than the AsyncTasks, hitting the same endpoint the same number of times. This translated into loading/parsing the data several seconds faster. That is a massive real-world difference. In order to make the tests fair, the times for AsyncTasks/Volley included the JSON parsing as Retrofit does it for you automatically.
Other advantages include:
- Declarative API Definition: Retrofit allows you to define your API endpoints using simple and elegant interface methods, abstracting away the complexities of HTTP client code.
- Automatic JSON Parsing: With Retrofit's integration of Gson or other converters, JSON responses are automatically converted into Java or Kotlin objects, saving you time and effort.
- Synchronous and Asynchronous Support: Retrofit seamlessly integrates with Kotlin coroutines, RxJava, and other asynchronous mechanisms, allowing you to perform network requests without blocking the UI thread.
- Interceptors and Customization: You can customize network requests by using interceptors to add headers, logging, or other modifications.
Integrating Retrofit into your app
The first step of integrating Retrofit into your Android app requires setting up your dependencies:
In your app-level build.gradle(:app) file, include the Retrofit, Son and OKHTTP dependencies:
In your project-level build.gradle file, add your dependencies versions for better access and maintenance:
If you use version catalogs, your dependencies should look as such, in your libs.versions.toml file, add the dependencies versions and libraries:
In your app-level build.gradle(:app) file, include your libraries:
The next step is to create the Data Transfer Object ( DTO ) which will be used to encapsulate the response parameters of the API call. We will be using the Moshi library to de-serialize the JSON and convert it to the required parameter type.
We will also be accounting for situations in which the response might return nothing in certain cases, since we may be using the same data object for other API responses, by declaring a nullable default value. For extra safety, we will annotate each parameter with the @Json name tag for de-serialization.
For the following step, we will be designing an API interface, which will be used to send requests and receive responses using Retrofit.
We wish the function to be asynchronous, hence the suspend keyword.
This API Interface, Moshi, OKHTTP and Retrofit will be instantiated as a Factory pattern, since we will be needing to have it create new objects for us. To do so, we will declare the factories inside a module block using the Koin library for dependency injection.
Next up we will build the Moshi converter instance, the OKHTTP Interceptor and OKHTTP Client instances and we will be injecting these in our Retrofit builder.
Inside our Session Interceptor we will be storing our authorization token in our sharedPrefs and pass it in our header. For now, we will be generating a userId string with a random number.
Injecting the API Interface and a Coroutine Context Dispatcher with Koin DI, we call a suspending block on the IO thread to fetch the image from the response.
Inside our view model, since we are using the MVVM architecture, we open a coroutine scope and retrieve our image from the repository. Notice how the retrieved object is Image and not ImageDto. It's best practice to map the response from the DTO into a model which will be used for drawing UI elements, in our case, an image.
Additional Features
One of Retrofit library’s unique features is the handling of dynamic URLs. You can define a dynamic URL by encasing it inside a {…} curly bracket and annotating it with @Path.
In this example, we fetch booking details using a dynamic URL which contains the @Path annotated parts { userId } and { bookingNumber }.
Retrofit also provides a great error handling mechanism that allows you to catch exceptions thrown by Retrofit by encapsulating the API call inside a try{ … }catch( e: Exception ){ … } block and handle them the best way to suit your needs.
Retrofit also provides a Response object which allows you to handle HTTP errors by checking the response code and status.
Now that you have gained a basic understanding of Retrofit, you are now ready to explore its more advanced features and strategies to further optimize and improve your app’s networking layer. Remember that practice and experimentation are key to becoming proficient with Retrofit and networking in Android app development. Remember that practice and experimentation are key to becoming proficient with Retrofit and networking in Android app development.
Flaviu-Olimpiu Crișan
Android Developer