Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to dynamically set list of headers in Retrofit 2 (Android)

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).

like image 928
p-pat-ni Avatar asked Oct 30 '22 08:10

p-pat-ni


1 Answers

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());

like image 196
Lovis Avatar answered Nov 15 '22 06:11

Lovis