Retrofit 2 fundamentally changes the way requests are made. Especially for developers, who are used to Retrofit 1.9 or earlier versions, the new Call
class is something that takes time to get an understanding for. In this blog post, we'll show you some basic usage and features of this new mysterious class!
Before you learn more about the Call
class, you might want to check out all the other Retrofit topics:
Retrofit Series Overview
- Getting Started and Creating an Android Client
- Basics of API Description
- Creating a Sustainable Android Client
- URL Handling, Resolution and Parsing
- How to Change API Base Url at Runtime
- Multiple Server Environments (Develop, Staging, Production)
- Share OkHttp Client and Converters between Retrofit Instances
- Upgrade Guide from 1.9
- Beyond Android: Retrofit for Java Projects
- How to use OkHttp 3 with Retrofit 1
- Synchronous and Asynchronous Requests
- Send Objects in Request Body
- Add Custom Request Header
- Manage Request Headers in OkHttp Interceptor
- Dynamic Request Headers with @HeaderMap
- Multiple Query Parameters of Same Name
- Optional Query Parameters
- Send Data Form-Urlencoded
- Send Data Form-Urlencoded Using FieldMap
- How to Add Query Parameters to Every Request
- Add Multiple Query Parameter With QueryMap
- How to Use Dynamic Urls for Requests
- Constant, Default and Logic Values for POST and PUT Requests
- Cancel Requests
- Reuse and Analyze Requests
- Optional Path Parameters
- How to Send Plain Text Request Body
- Customize Network Timeouts
- How to Trust Unsafe SSL certificates (Self-signed, Expired)
- Dynamic Endpoint-Dependent Interceptor Actions
- How to Update Objects on the Server (PUT vs. PATCH)
- How to Delete Objects on the Server
- Introduction to (Multiple) Converters
- Adding & Customizing the Gson Converter
- Implementing Custom Converters
- How to Integrate XML Converter
- Access Mapped Objects and Raw Response Payload
- Supporting JSON and XML Responses Concurrently
- Handling of Empty Server Responses with Custom Converter
- Send JSON Requests and Receive XML Responses (or vice versa)
- Unwrapping Envelope Responses with Custom Converter
- Wrapping Requests in Envelope with Custom Converter
- Define a Custom Response Converter
Reuse of Call Objects
In this blog post, we'll make use of the code from our how to download files blog post. If you're interested in the details, give it a quick read. Otherwise, keep going. What kind of request it is, doesn't really matter. All the features we'll show you apply for all Retrofit requests.
One Request for Each Call Object
One of the first things you've to know about the Call
class and its instances: each instance is special made for one and only one request. You cannot simply use the same object and call execute()
or enqueue()
again:
FileDownloadService downloadService = ServiceGenerator.create(FileDownloadService.class);
Call<ResponseBody> originalCall = downloadService.downloadFileWithDynamicUrlSync(fileUrl);
Callback<ResponseBody> downloadCallback = new Callback<ResponseBody>() {...};
// correct usage:
originalCall.enqueue(downloadCallback);
// some other actions in between
// ...
// incorrect reuse:
// if you need to make the same request again, don't use the same originalCall again!
// it'll crash the app with a java.lang.IllegalStateException: Already executed.
originalCall.enqueue(downloadCallback); // <-- would crash the app
Duplicated Call Objects
Instead, if you want to make the exact same request again, you can use the clone()
method on the Call
instance to create a copy of it. It'll contain the exact same settings and configuration. You can use the new copy to make an identical request to the server:
FileDownloadService downloadService =
ServiceGenerator.create(FileDownloadService.class);
Call<ResponseBody> originalCall =
downloadService.downloadFileWithDynamicUrlSync(fileUrl);
Callback<ResponseBody> downloadCallback = new Callback<ResponseBody>() {...};
// correct reuse:
Call<ResponseBody> newCall = originalCall.clone();
newCall.enqueue(downloadCallback);
This can be very useful if you need to send the same request multiple times.
Analyzing Requests With the Call Object
As you've already seen, Retrofit 2 includes the Call
instance to every callback method. Thus, if the request was successful or even if it failed, you still can access the original Call
object. But the reason to include it is not so that you can reuse the call
(hint: use clone()
), it's that you can analyze the request that was made using call.request()
. This will return the complete request data. Let's look at an example:
FileDownloadService downloadService =
ServiceGenerator.create(FileDownloadService.class);
Call<ResponseBody> originalCall =
downloadService.downloadFileWithDynamicUrlSync(fileUrl);
originalCall.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
checkRequestContent(call.request());
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
checkRequestContent(call.request());
}
});
Both callback methods are passing the request to a new helper method checkRequestContent()
, which accesses the request headers, body and url:
private void checkRequestContent(Request request) {
Headers requestHeaders = request.headers();
RequestBody requestBody = request.body();
HttpUrl requestUrl = request.url();
// todo make decision depending on request content
}
This might be useful to you if you want to review the request, which was send to the server.
Preview Requests
It's also good to know that you can utilize call.request()
at any time, even if the request wasn't scheduled or made yet! It'll generate the request just like it would for a regular network call.
Important: the call.request()
method does some significant computing, if the request wasn't executed yet. It's not recommended to get a preview of the data via .request()
on Android's UI/Main thread!
Summary
In this blog post, we've made you a little more familiar with the Call
class and how to use it. We've shown that you can use each instance only once. Furthermore, we've also shown you a way how to duplicate requests. Finally, you've learned how you can analyze the request content at any time!
Do you have a firm grasp of the Call
class yet? Let us know in the comments!