Retrofit is a type-safe HTTP client for Android, developed by Square in Java. The library allows you to define REST APIs through Java interfaces with annotations, automatically converting HTTP responses into Java objects. According to the Retrofit repository on GitHub, the project is used by more than 42,000 projects worldwide. The library remains the standard for network requests in Android development.
Key Takeaways
Retrofit is a library for making HTTP requests in Android applications, developed by Square. It provides a declarative approach to defining REST APIs through Java interfaces with annotations, making network interaction code clean and predictable.
The core idea of Retrofit is that the developer describes the API as an interface with methods and annotations, and the library generates the implementation automatically. This approach ensures that all endpoints are typed, and errors in URLs or parameters are detected at compile time rather than at runtime.
Retrofit supports all popular HTTP methods and data formats. The library is actively maintained by Square and the community: new releases come out regularly, and the current version 2.11 includes support for Java 17 and Kotlin 2.0. Retrofit remains the most popular HTTP client for Android.
Retrofit runs on top of OkHttp — an efficient HTTP client also from Square. This combination provides caching, request interception, and connection management at the transport protocol level. The library supports both synchronous and asynchronous calls.
Since its first release in 2013, Retrofit has gone through several major updates. The current version Retrofit 2 has been completely rewritten based on experience with the first version and offers a more flexible system of converters and adapters for asynchrony.
Retrofit's architecture follows the principle of separation of concerns: the interface defines only the API contract, converters handle serialization, and adapters manage asynchrony. This allows replacing any component without changing the rest of the code. For example, you can switch from Gson to Moshi without changing endpoint definitions.
Retrofit provides a set of features that cover virtually all network interaction scenarios in mobile applications. The key advantage is the declarative style of API definition.
Annotations @GET, @POST, @PUT, @PATCH, @DELETE and @HTTP allow you to specify the HTTP method and URL template directly in the interface. Path parameters are set via @Path, query parameters via @Query, and the request body via @Body. This approach makes the application's API layer fully typed.
Converters transform HTTP responses into Java objects and vice versa. Retrofit supports Gson, Moshi, Jackson, Protobuf and Wire. The developer connects the required converter via Converter.Factory, and the library automatically applies it to all requests and responses.
Adapters CallAdapter allow changing the return type of API methods. Instead of the standard Call, you can use Observable for RxJava, Deferred for Kotlin coroutines, or LiveData. This integrates network requests with the chosen application architecture.
Dynamic URLs are set via @Url annotations, allowing you to pass the endpoint at runtime. Headers can be specified statically via @Headers or dynamically via the @Header parameter. For global headers across all requests, an OkHttp interceptor is used, which adds headers to each outgoing request.
Retrofit works in three stages: defining the API interface, creating a Retrofit instance, and executing the request. The library generates the interface implementation at runtime based on annotations and converters.
When an API method is called, Retrofit creates a Request object based on the annotations and arguments. The request is passed to OkHttp for execution. After receiving the response, the library passes it to Converter.Factory for transformation into the required type. CallAdapter wraps the result in an asynchronous wrapper. Each stage can be customized.
interface ApiService {
@GET("users/{id}")
suspend fun getUser(@Path("id") id: Int): User
}
val retrofit = Retrofit.Builder()
.baseUrl("https://api.example.com/")
.addConverterFactory(GsonConverterFactory.create())
.build()
val api = retrofit.create(ApiService::class.java)
Installation of Retrofit is done through Gradle — the standard Android build system. The library is distributed via Maven Central and requires adding several dependencies to the project's build.gradle.
In the build.gradle file (module level), add dependencies for Retrofit, Gson converter, and OkHttp. It is recommended to extract library versions into variables in the root build.gradle for centralized management. Retrofit 2 requires a minimum of Android API 21.
dependencies {
implementation "com.squareup.retrofit2:retrofit:2.11.0"
implementation "com.squareup.retrofit2:converter-gson:2.11.0"
implementation "com.squareup.okhttp3:okhttp:4.12.0"
implementation "com.squareup.okhttp3:logging-interceptor:4.12.0"
}
A Retrofit instance is created via Builder. Required parameters: baseUrl and ConverterFactory. It is recommended to use a singleton for Retrofit and OkHttpClient to avoid creating redundant connections. Adding a logging-interceptor simplifies debugging network requests during development.
For Kotlin projects, it is recommended to use suspend functions in the API interface instead of Call types. This simplifies the code and allows using structured concurrency of coroutines. When switching from Call to suspend, you only need to change the return type in the interface — the rest of the code adapts automatically.
The examples below demonstrate typical scenarios of working with Retrofit in Android applications: from a simple GET request to uploading a file to the server.
A simple GET request with query string parameters is a basic operation. The @Query annotation adds parameters to the URL automatically, and the suspend function allows calling the request from a coroutine without blocking the main thread.
interface UserApi {
@GET("users")
suspend fun getUsers(
@Query("page") page: Int,
@Query("limit") limit: Int = 20
): List<User>
}
val users = api.getUsers(page = 1)
A POST request with a JSON body uses the @Body annotation to pass the object. GsonConverterFactory automatically serializes the User object into JSON. Kotlin coroutines ensure the request is executed in the background thread without Callback interfaces.
interface UserApi {
@POST("users")
suspend fun createUser(@Body user: User): User
}
val user = User(name = "Anna Ivanova", email = "anna@example.com")
val created = api.createUser(user)
The @Multipart annotation with @Part allows uploading files to the server. Retrofit automatically forms a multipart request with the required headers. OkHttp manages upload progress through RequestBody, allowing you to display an indicator to the user.
interface FileApi {
@Multipart
@POST("upload")
suspend fun uploadImage(
@Part file: MultipartBody.Part
): UploadResponse
}
val body = "image.jpg".toRequestBody("image/jpeg".toMediaTypeOrNull())
val part = MultipartBody.Part.createFormData("file", "image.jpg", body)
Error handling in Retrofit is built on a combination of OkHttp mechanisms and Kotlin coroutines. OkHttp interceptors allow logging requests, adding authentication headers, and handling errors before they reach the application code.
For centralized error handling, a wrapper around API calls is often created as a sealed class Result. Such a class has two subclasses: Success with data and Error with an exception. The ViewModel receives a unified result and can display the corresponding user interface state without duplicating error handling code in each function.
Interceptors come in two types: application interceptors modify the request before it is sent to the server, and network interceptors work with the response after it is received. For example, an interceptor can automatically refresh the access token upon receiving a 401 and retry the request with the new token without developer involvement.
The logging interceptor HttpLoggingInterceptor is an indispensable tool for debugging network requests. It outputs the request method, URL, headers, body, and response code to Logcat. The logging level can be configured: BASIC for minimal information, HEADERS for headers, or BODY for full content. In production, it is recommended to use BASIC or disable logging entirely.
Interceptors in OkHttp are divided into two types: application interceptors for modifying the request and network interceptors for working with raw network data. The logging interceptor automatically outputs request and response details to Logcat.
Error handling at the coroutine level is done via try-catch around the suspend function call. Retrofit returns errors as HttpException for 4xx and 5xx codes, UnknownHostException when there is no network, and SocketTimeoutException when a timeout occurs. It is recommended to use a sealed class Result for unified handling.
Frequently Asked Questions
Retrofit is a high-level wrapper over OkHttp. OkHttp performs low-level HTTP operations, while Retrofit adds declarative annotations, converters, and adapters. Typically, projects use both libraries together.
Errors are handled via try-catch around the suspend call. It is recommended to use a Result class to return either successful data or an error. This avoids multiple catch blocks in each ViewModel.
Retrofit supports Gson, Moshi, Jackson, Protobuf, Wire, Simple XML, and Scalars. Each converter is connected via Converter.Factory. The most popular are GsonConverterFactory and MoshiConverterFactory.
No, Retrofit is tightly coupled to OkHttp and does not support other HTTP clients. For multiplatform projects in Kotlin, use Ktor, which works on all platforms, including iOS and JS.
Timeout is configured through OkHttpClient. Set the connectTimeout, readTimeout, and writeTimeout properties when creating the client, then pass it to Retrofit.Builder.client(). Default values are 10 seconds.
Summary
We will develop a mobile application turnkey
IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.
Read also