Adding request parameters can be kind of pain in the a** if your service methods allows multiple query parameters which also can be optional. We’ve published an article describing how to use optional query parameters. Today, we’re going to simplify the handling of multiple query parameters by introducing and using the @QueryMap
annotation.
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
What is @QueryMap
in Retrofit?
Retrofit uses annotations to translate defined keys and values into appropriate format. Using the @Query("key") String value
annotation will add a query parameter with name key
and the respective string value to the request url (of course you can use other types than string :)).
Actually, there are APIs with endpoints allowing you to pass (optionally) multiple query parameters. You want to avoid a service method declaration like the one below with “endless” options for request parameters:
public interface NewsService() {
@GET("/news")
Call<List<News>> getNews(
@Query("page") int page,
@Query("order") String order,
@Query("author") String author,
@Query("published_at") Date date,
…
);
}
You could call the .getNews
service method with null
values for each of the parameters to make them optional. Retrofit will ignore null
values and don’t map them as query parameters. However, there is a better solution to work with complex API endpoints having various options for query parameters. Don’t worry, Retrofit got you covered!
How to Use QueryMap
The @QueryMap
annotation expects a Map with key-value-pairs of type String
. Each key which has a non-null value will be mapped and you can dynamically add your desired query parameters.
public interface NewsService() {
@GET("/news")
Call<List<News>> getNews(
@QueryMap Map<String, String> options
);
}
If you want to request the news from page 2
of author Marcus
, you only need to add the map entries for page
and author
. There’s no need to worry about the other available options.
The following snippet illustrates how to execute the actual request to fetch the news.
private void fetchNews() {
Map<String, String> data = new HashMap<>();
data.put("author", "Marcus");
data.put("page", String.valueOf(2));
// simplified call to request the news with already initialized service
Call<List<News>> call = newsService.getNews(data);
call.enqueue(…);
}
The resulting url with the assumed example (page 2 of Marcus):
http://your.api.url/news?page=2&author=Marcus
QueryMap Options
The @QueryMap
annotation has an option field for encoding:
encoded
: can be eithertrue
orfalse
; default isfalse
You can set the value for encoding
like this:
Call<List<News>> getNews((@QueryMap(encoded=true) Map<String, String> options);
Enabling encoding
will encode individual characters before appended to the request url. Using the key author
with value marcus-poehls
will result in the following encoded url: author=marcus%2Dpoehls
.
Setting encoding
to false
(by default), the url for the example above would be author=marcus-poehls
.
Outlook
Retrofit’s @QueryMap
annotation is a convenient way to add multiple query parameters to a request without pre-defining their actual names. That gives you more freedom for requests by just passing the map with key-value-pairs to the service method, but doesn’t show you which options are available. It’s up to you to read the API documentation. We hope you’ve having a commendable backend developer :)