Instruction
Introducing Retrofit Call
The Call<T> interface in Retrofit represents a single network request and response. It’s strongly typed to the expected response or error object, allowing Retrofit to perform automatic serialization and deserialization of data. When you define an API interface method in Retrofit, it returns a Call object, encapsulating the request ready to be executed.
For example:
@GET("user")
fun getProfile(): Call<User>
This method returns a Call object that, when executed, makes an HTTP GET request to the specified endpoint and attempts to parse the response into a User object.
To auto-parse responses into Kotlin objects, Retrofit needs a Converter. You’ll add that in the next lesson. For now, you’ll learn how to manually parse the response.
Reading the ResponseBody
You handle raw responses from the server using Retrofit’s ResponseBody. Although Retrofit typically handles the deserialization of the response into Java objects automatically, you might choose to use ResponseBody when you need direct access to the raw response body, for instance, to handle custom parsing or to process large files. Custom parsing is what you’ll do in this lesson.
For example:
@GET("user")
fun getProfile(): Call<ResponseBody>
To get the raw server response, you set the return type of the method to be Call<ReponseBody>.
Closing the ReponseBody
Maintaining an active connection to the web server is essential for supporting each ResponseBody. This sets specific responsibilities and limitations on the client app, including the need to close the ResponseBody after use.
Neglecting to close the response body can lead to resource leakage, potentially slowing or even crashing the app. In this lesson, you’ll use Response.body().string(), to read the response as a string and close it afterward.
You can find out more about different ways of closing ReponseBody in the source code for OkHttp.
Sending a RequestBody
A RequestBody in Retrofit represents the body of an HTTP request. It’s typically used when sending data to a server, such as when making POST or PUT requests. Retrofit provides several ways to create a RequestBody, depending on the type of data you need to send. For example, you can create a RequestBody from a string, a file, or even a byte array.
val body = RequestBody.create(MediaType.parse("application/json"), jsonBody)
The code above shows an example of how to create a RequestBody from a string. application/json signals to the API that you’re sending data in JSON format. jsonBody is a JSON string that will be sent as the body.
The following code shows how you can define your service interface methods to have a body parameter:
@POST("user/register")
fun registerUser(@Body body: RequestBody): Call<ResponseBody>
@Body is Retrofit’s annotation that signals this parameter should be treated as a body of the API request. In this case, the parameter is of type RequestBody, but it doesn’t always have to be. In the next lesson, you’ll pass Kotlin objects as a body.
Making Synchronous vs. Asynchronous Requests
execute(): This method executes the request synchronously on the current thread, blocking the thread until the response is received or an error occurs. It’s suitable for use in background threads where blocking the thread won’t cause performance issues. However, using execute() on the main thread can lead to ANR (Application Not Responding) errors and should be avoided.
enqueue(): On the other hand, enqueue() executes the request asynchronously on a background thread. It doesn’t block the calling thread and instead uses a callback mechanism to deliver the response or error once it’s available. This method is recommended for use on the main thread to avoid blocking the UI and ensure a smooth user experience.
Note: You should always use
enqueue()by default. Only useexecute()if you’re sure that you need it.
With a solid amount of theory behind you, proceed to the next section where you’ll apply the theoretical knowledge. You can continue where you left off or you can download the starter project for this lesson.