Dagger 生成多个改造拦截器实例
Dagger generating multiple instances of retrofit interceptor
我是 Dagger 和 Retrofit 的新手。我遇到问题,尽管在匕首模块中声明了单例,但仍在生成改装自定义拦截器的多个实例。我只需要一个实例。
匕首模组
@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();
}
}
改装拦截器
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());
}
}
连接器
public class Connect
{
@Inject Retrofit retrofit;
@Inject Config config;
@Inject AuthenticationRequestInterceptor headerInterceptor;
public Connect(PercentApp application)
{
((PercentApp) application).getComponent().inject(this);
/** Setting interceptor headers here, but this get sets in a different
instances than the one gets 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);
}
}
}
在我的应用程序中,我创建了这样的 Dagger 实例:
DaggerApplicationComponent.builder()
.applicationModule(new ApplicationModule(this))
.apiModule(new ApiModule(new Config(environment)))
.build();
And in my MainActivity I create instance of Connect
Connect connect = new Connect((MyApp) getApplication());
User user = new User();
connect.postUser(new UserObserver(this), user);
现在的问题是 AuthenticationRequestInterceptor 构造函数被调用了两次,我不明白为什么,因此我设置的 headers get 设置为不同的拦截器的实例。请帮忙。谢谢
你不应该直接调用 provideRequestInterceptor
@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();
}
在 provideRetrofitInstance 方法中创建了另一个实例 OkHttpClient.Builder,您已经在 ApiModule 中提供了它。保持友善并改用 httpClient 参数。
@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();
}
}
我是 Dagger 和 Retrofit 的新手。我遇到问题,尽管在匕首模块中声明了单例,但仍在生成改装自定义拦截器的多个实例。我只需要一个实例。
匕首模组
@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();
}
}
改装拦截器
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());
}
}
连接器
public class Connect
{
@Inject Retrofit retrofit;
@Inject Config config;
@Inject AuthenticationRequestInterceptor headerInterceptor;
public Connect(PercentApp application)
{
((PercentApp) application).getComponent().inject(this);
/** Setting interceptor headers here, but this get sets in a different instances than the one gets 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);
}
}
}
在我的应用程序中,我创建了这样的 Dagger 实例:
DaggerApplicationComponent.builder()
.applicationModule(new ApplicationModule(this))
.apiModule(new ApiModule(new Config(environment)))
.build();
And in my MainActivity I create instance of Connect
Connect connect = new Connect((MyApp) getApplication());
User user = new User();
connect.postUser(new UserObserver(this), user);
现在的问题是 AuthenticationRequestInterceptor 构造函数被调用了两次,我不明白为什么,因此我设置的 headers get 设置为不同的拦截器的实例。请帮忙。谢谢
你不应该直接调用 provideRequestInterceptor
@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();
}
在 provideRetrofitInstance 方法中创建了另一个实例 OkHttpClient.Builder,您已经在 ApiModule 中提供了它。保持友善并改用 httpClient 参数。
@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();
}
}