We are trying to migrate to using Retrofit2 and I am having trouble with a requirement where we need to pass a set of dynamically generated headers (used for analytics) for every request.
@Headers is not supported at parameter level and since header field name vary based on the current activity, I cannot use @Header.
Is there a way to append the headers just before execute() ? (Looking for something similar to @QueryMap/@FieldMap but for headers)
NOTE: I do not have the list of headers while initializing the client (and hence cannot use the Interceptor to do this).
You still can (and have to) use the Interceptor.
All you need is a little Architecture.
First create a helper that provides the necessary headers.
public class AnalyticsHeader {
private String analyticsHeaderName;
private String analyticsHeaderValue;
public void setHeaderValue(String header) {
this.analyticsHeaderValue = header;
}
public void setHeaderName(String header) {
this.analyticsHeaderName = header;
}
public String getHeaderName() {
return analyticsHeaderName;
}
public String getHeaderValue() {
return analyticsHeaderValue;
}
}
Keep an instance of this class in a accessible place inside your app, for example the MainActivity our the Application (or even better, use Dependency Injection)
Now, upon creation of the Interceptor just pass the instance of the AnalyticsHeader into the Interceptor:
public static final class AnalyticsInterceptor implements Interceptor {
private final AnalyticsHeader header;
public AnalyticsInterceptor(AnalyticsHeader header) {
this.header = header;
}
@Override
public Response intercept(Chain chain) throws IOException {
final Request original = chain.request();
Response response;
if (header.getHeader() != null) {
Request request = original.newBuilder()
.header(header.getHeaderName(), header.getHeaderValue())
.method(original.method(), original.body())
.build();
response = chain.proceed(request);
} else {
response = chain.proceed(original);
}
return response;
}
}
And then...
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.addInterceptor(new AnalyticsInterceptor(CentralPlaceInApp.getAnalyticsHeader());
...
retrofit = new Retrofit.Builder()
.baseUrl(config.getRestUrl())
.client(builder.build())
.build();
Now, you can change the value of the header anytime during your app runtime using CentralPlaceInApp.getAnalyticsHeader().setHeaderValue(CurrentActivity.class.getSimpleName());
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With