gpt4 book ai didi

Android Dagger2 + OkHttp + Retrofit 依赖循环错误

转载 作者:可可西里 更新时间:2023-11-01 18:59:59 24 4
gpt4 key购买 nike

嘿,我正在使用 Dagger2RetrofitOkHttp,我面临着依赖循环问题。

当提供 OkHttp 时:

@Provides
@ApplicationScope
OkHttpClient provideOkHttpClient(TokenAuthenticator auth,Dispatcher dispatcher){
return new OkHttpClient.Builder()
.connectTimeout(Constants.CONNECT_TIMEOUT, TimeUnit.SECONDS)
.readTimeout(Constants.READ_TIMEOUT,TimeUnit.SECONDS)
.writeTimeout(Constants.WRITE_TIMEOUT,TimeUnit.SECONDS)
.authenticator(auth)
.dispatcher(dispatcher)
.build();
}

当提供Retrofit时:

@Provides
@ApplicationScope
Retrofit provideRetrofit(Resources resources,Gson gson, OkHttpClient okHttpClient){
return new Retrofit.Builder()
.baseUrl(resources.getString(R.string.base_api_url))
.addConverterFactory(GsonConverterFactory.create(gson))
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.client(okHttpClient)
.build();
}

提供APIService时:

@Provides
@ApplicationScope
APIService provideAPI(Retrofit retrofit) {
return retrofit.create(APIService.class);
}

我的 APIService 接口(interface):

public interface  APIService {
@FormUrlEncoded
@POST("token")
Observable<Response<UserTokenResponse>> refreshUserToken();

--- other methods like login, register ---

}

我的 TokenAuthenticator 类:

@Inject
public TokenAuthenticator(APIService mApi,@NonNull ImmediateSchedulerProvider mSchedulerProvider) {
this.mApi= mApi;
this.mSchedulerProvider=mSchedulerProvider;
mDisposables=new CompositeDisposable();
}

@Override
public Request authenticate(Route route, Response response) throws IOException {

request = null;

mApi.refreshUserToken(...)
.subscribeOn(mSchedulerProvider.io())
.observeOn(mSchedulerProvider.ui())
.doOnSubscribe(d -> mDisposables.add(d))
.subscribe(tokenResponse -> {
if(tokenResponse.isSuccessful()) {
saveUserToken(tokenResponse.body());
request = response.request().newBuilder()
.header("Authorization", getUserAccessToken())
.build();
} else {
logoutUser();
}
},error -> {

},() -> {});

mDisposables.clear();
stop();
return request;

}

我的日志:

Error:(55, 16) error: Found a dependency cycle:
com.yasinkacmaz.myapp.service.APIService is injected at com.yasinkacmaz.myapp.darkvane.modules.NetworkModule.provideTokenAuthenticator(…, mApi, …)
com.yasinkacmaz.myapp.service.token.TokenAuthenticator is injected at
com.yasinkacmaz.myapp.darkvane.modules.NetworkModule.provideOkHttpClient(…, tokenAuthenticator, …)
okhttp3.OkHttpClient is injected at
com.yasinkacmaz.myapp.darkvane.modules.NetworkModule.provideRetrofit(…, okHttpClient)
retrofit2.Retrofit is injected at
com.yasinkacmaz.myapp.darkvane.modules.NetworkModule.provideAPI(retrofit)
com.yasinkacmaz.myapp.service.APIService is provided at
com.yasinkacmaz.myapp.darkvane.components.ApplicationComponent.exposeAPI()

所以我的问题是:我的 TokenAuthenticator 类依赖于 APIService 但我需要在创建 APIService 时提供 TokenAuthenticator >。这会导致依赖循环错误。我该如何解决这个问题,有人面临这个问题吗?提前致谢。

最佳答案

你的问题是:

  1. 您的 OKHttpClient 取决于您的 Authenticator
  2. 您的身份验证器依赖于 Retrofit 服务
  3. Retrofit 依赖于 OKHttpClient(如第 1 点)

因此循环依赖。

一个可能的解决方案是让您的 TokenAuthenticator 依赖于 APIServiceHolder 而不是 APIService。然后你的 TokenAuthenticator 可以在配置 OKHttpClient 时作为依赖项提供,而不管 APIService (在对象图的下方)是否已经被实例化.

一个非常简单的 APIServiceHolder:

public class APIServiceHolder {

private APIService apiService;

@Nullable
APIService apiService() {
return apiService;
}

void setAPIService(APIService apiService) {
this.apiService = apiService;
}
}

然后重构您的 TokenAuthenticator:

@Inject
public TokenAuthenticator(@NonNull APIServiceHolder apiServiceHolder, @NonNull ImmediateSchedulerProvider schedulerProvider) {
this.apiServiceHolder = apiServiceHolder;
this.schedulerProvider = schedulerProvider;
this.disposables = new CompositeDisposable();
}

@Override
public Request authenticate(Route route, Response response) throws IOException {

if (apiServiceHolder.get() == null) {
//we cannot answer the challenge as no token service is available

return null //as per contract of Retrofit Authenticator interface for when unable to contest a challenge
}

request = null;

TokenResponse tokenResponse = apiServiceHolder.get().blockingGet()

if (tokenResponse.isSuccessful()) {
saveUserToken(tokenResponse.body());
request = response.request().newBuilder()
.header("Authorization", getUserAccessToken())
.build();
} else {
logoutUser();
}

return request;
}

请注意,检索 token 的代码应该是同步的。这是 Authenticator 契约的一部分。 Authenticator 中的代码将关闭 主线程。

当然,您需要为此编写@Provides 方法:

@Provides
@ApplicationScope
apiServiceHolder() {
return new APIServiceHolder();
}

并重构提供者方法:

@Provides
@ApplicationScope
APIService provideAPI(Retrofit retrofit, APIServiceHolder apiServiceHolder) {
APIService apiService = retrofit.create(APIService.class);
apiServiceHolder.setAPIService(apiService);
return apiService;
}

请注意,可变全局状态通常不是一个好主意。但是,如果您的包组织得很好,您可以适本地使用访问修饰符来避免持有者的意外使用。

关于Android Dagger2 + OkHttp + Retrofit 依赖循环错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43914605/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com