Dagger creating multiple instances of the modified interceptor

I am new to dagger and retrofit. I have a problem when multiple instances of a modified custom interceptor are generated, despite the declared singleton in the dagger module. I need only one instance.

Dagger module

@Module public class ApiModule { private Config config; public ApiModule(Config config) { this.config = config; } @Provides @Singleton public OkHttpClient.Builder provideOkHttpClient() { return new OkHttpClient.Builder(); } @Provides @Singleton public AuthenticationRequestInterceptor provideRequestInterceptor() { return new AuthenticationRequestInterceptor(); } @Provides @Singleton public Retrofit provideRetrofitInstance() { HttpLoggingInterceptor logging = new HttpLoggingInterceptor(); // set your desired log level logging.setLevel(HttpLoggingInterceptor.Level.BODY); OkHttpClient.Builder httpClient = new OkHttpClient.Builder(); // add session headers interceptor httpClient.addInterceptor(provideRequestInterceptor()); // add logging as last interceptor httpClient.addInterceptor(logging); return new Retrofit.Builder() .baseUrl(getConfig().getBaseUrl()) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .client(httpClient.build()) //for logging purpose remove later .build(); } } 

Refit interceptor

 public class AuthenticationRequestInterceptor implements Interceptor { private Map<String, String> defaultHeaders; public AuthenticationRequestInterceptor() { this.defaultHeaders = new HashMap<>(); } public void setDefaultHeaders(Map<String, String> headers) { this.defaultHeaders = headers; } @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); Request.Builder requestBuilder = request.newBuilder(); for (String key: this.defaultHeaders.keySet()) { requestBuilder.addHeader(key, this.defaultHeaders.get(key)); } return chain.proceed(requestBuilder.build()); } } 

Connector

 public class Connect { @Inject Retrofit retrofit; @Inject Config config; @Inject AuthenticationRequestInterceptor headerInterceptor; public Connect(PercentApp application) { ((PercentApp) application).getComponent().inject(this); 

/ ** Interceptor headers are set here, but this is obtained in different instances that are called later in postUser ** /

  headerInterceptor.setDefaultHeaders(generateDefaultAuthHeaders()); } public void postUser(Observer observer, User user) { if(retrofit != null) { ApiServices api = retrofit.create(ApiServices.class); Observable<HashMap> observable = api.postUser("{post something}"); observable. subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(observer); } } } 

And in my application, I create a dagger instance as follows:

 DaggerApplicationComponent.builder() .applicationModule(new ApplicationModule(this)) .apiModule(new ApiModule(new Config(environment))) .build(); 

And in my MainActivity I create an instance of Connect

 Connect connect = new Connect((MyApp) getApplication()); User user = new User(); connect.postUser(new UserObserver(this), user); 

Now the problem is that the calling AuthenticationRequestInterceptor call is called twice, which I don’t understand why, and because of this, the headers I set are set to another Interceptor instance. Please help. thank

+1
android retrofit2 dagger-2 rx-java2
Jul 13 '17 at 11:01
source share
2 answers

You should not call provideRequestInterceptor directly

 @Provides @Singleton public Retrofit provideRetrofitInstance(AuthenticationRequestInterceptor authInterceptor) { HttpLoggingInterceptor logging = new HttpLoggingInterceptor(); // set your desired log level logging.setLevel(HttpLoggingInterceptor.Level.BODY); OkHttpClient.Builder httpClient = new OkHttpClient.Builder(); // add session headers interceptor httpClient.addInterceptor(authInterceptor); // add logging as last interceptor httpClient.addInterceptor(logging); return new Retrofit.Builder() .baseUrl(getConfig().getBaseUrl()) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .client(httpClient.build()) //for logging purpose remove later .build(); } 
+1
Jul 13. '17 at 12:02 on
source share

There is a point to create another instance of OkHttpClient.Builder in the RetrofitInstance provisioning method that you already provided in your ApiModule. Be nice and use the httpClient argument instead.

 @Module public class ApiModule { private Config config; public ApiModule(Config config) { this.config = config; } @Provides @Singleton public OkHttpClient.Builder provideOkHttpClient() { return new OkHttpClient.Builder(); } @Provides @Singleton public AuthenticationRequestInterceptor provideRequestInterceptor() { return new AuthenticationRequestInterceptor(); } @Provides @Singleton public Retrofit provideRetrofitInstance(OkHttpClient.Builder httpClient, AuthenticationRequestInterceptor authInterceptor) { HttpLoggingInterceptor logging = new HttpLoggingInterceptor(); // set your desired log level logging.setLevel(HttpLoggingInterceptor.Level.BODY); //YOU DON'T THIS LINE, REFER TO ARGUMENT LIST //OkHttpClient.Builder httpClient = new OkHttpClient.Builder(); // add session headers interceptor httpClient.addInterceptor(authInterceptor); // add logging as last interceptor httpClient.addInterceptor(logging); return new Retrofit.Builder() .baseUrl(getConfig().getBaseUrl()) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .client(httpClient.build()) //for logging purpose remove later .build(); } } 
0
Nov 16 '17 at 11:49
source share



All Articles