如何摆脱这个令牌认证器 Hilt 依赖循环?
How to get out of this token authenticator Hilt dependency cycle?
我有一个 returns 一个 API 的函数,它需要一个 OkHttpClient 实例
@Module
@InstallIn(ApplicationComponent::class)
object AuthNetworkModule {
@Provides
fun provideAuthRetrofitService (@AuthQualifier okHttpClient: OkHttpClient): IQuipsAuth{
return Retrofit.Builder()
.baseUrl("${Config.BASE_URL}/")
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create(GsonBuilder().setLenient().create()))
.build().create(IQuipsAuth::class.java)
}
而且我还有一个功能,returns 一个需要 API 身份验证器实例的 OkHttpClient,我该怎么做?
@Provides
@AuthQualifier
fun provideOkHttpClient (application: Application, iQuipsAuth: IQuipsAuth): OkHttpClient {
val interceptor = HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger {
override fun log(message: String) {
Log.d("HttpLoggingInterceptor", message)
}
}).setLevel(HttpLoggingInterceptor.Level.HEADERS)
return OkHttpClient.Builder()
.readTimeout(180, TimeUnit.SECONDS)
.writeTimeout(45, TimeUnit.SECONDS)
.hostnameVerifier { _: String?, _: SSLSession? -> true }
.addInterceptor(interceptor)
.addInterceptor(AccessTokenInterceptor(application, iQuipsAuth))
.authenticator(AccessTokenAuthenticator(application, iQuipsAuth))
.build()
}
}
我正在尝试在 Hilt 中重新创建相同的 Koin 代码:
single {
val interceptor = HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger {
override fun log(message: String) {
Log.d("HttpLoggingInterceptor", message)
}
}).setLevel(HttpLoggingInterceptor.Level.BODY)
val okHttpClient = OkHttpClient.Builder()
.readTimeout(180, TimeUnit.SECONDS)
.writeTimeout(45, TimeUnit.SECONDS)
.hostnameVerifier { _: String?, _: SSLSession? -> true }
.addInterceptor(interceptor)
.build()
val retrofit = Retrofit.Builder()
.baseUrl("${Config.baseUrl}/")
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create(get()))
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build()
retrofit.create(IQuipsAuth::class.java)
}
您似乎想要两个不同的 OkHttpClient
。 IQuipsAuth
取决于哪个不使用 AccessTokenInterceptor
或 AccessTokenAuthenticator
(直接与 Auth 服务对话时你真的想要那些吗?)。另一个 OkHttpClient
将用于使用 IQuipsAuth
进行身份验证的其他服务。
您可以使用限定符区分同一类型的两个实例。下面是关于使用带有刀柄的限定符的片段:https://developer.android.com/training/dependency-injection/hilt-android#multiple-bindings
您可以使用 dagger.Lazy<T>
.
解决依赖循环
fun provideOkHttpClient (application: Application, iQuipsAuth: Lazy<IQuipsAuth>): OkHttpClient {
// ...
.addInterceptor(AccessTokenInterceptor(application, iQuipsAuth)) // pass lazy
.authenticator(AccessTokenAuthenticator(application, iQuipsAuth)) // pass lazy
// ...
}
然后在实际使用客户端时调用lazy.get()
。
请注意,如果 AccessTokenInterceptor
和 AccessTokenAuthenticator
都使用 @Inject constructor
提供给 Dagger,并提供给此 @Provides
方法,这将更加不言自明作为方法的参数。
我有一个 returns 一个 API 的函数,它需要一个 OkHttpClient 实例
@Module
@InstallIn(ApplicationComponent::class)
object AuthNetworkModule {
@Provides
fun provideAuthRetrofitService (@AuthQualifier okHttpClient: OkHttpClient): IQuipsAuth{
return Retrofit.Builder()
.baseUrl("${Config.BASE_URL}/")
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create(GsonBuilder().setLenient().create()))
.build().create(IQuipsAuth::class.java)
}
而且我还有一个功能,returns 一个需要 API 身份验证器实例的 OkHttpClient,我该怎么做?
@Provides
@AuthQualifier
fun provideOkHttpClient (application: Application, iQuipsAuth: IQuipsAuth): OkHttpClient {
val interceptor = HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger {
override fun log(message: String) {
Log.d("HttpLoggingInterceptor", message)
}
}).setLevel(HttpLoggingInterceptor.Level.HEADERS)
return OkHttpClient.Builder()
.readTimeout(180, TimeUnit.SECONDS)
.writeTimeout(45, TimeUnit.SECONDS)
.hostnameVerifier { _: String?, _: SSLSession? -> true }
.addInterceptor(interceptor)
.addInterceptor(AccessTokenInterceptor(application, iQuipsAuth))
.authenticator(AccessTokenAuthenticator(application, iQuipsAuth))
.build()
}
}
我正在尝试在 Hilt 中重新创建相同的 Koin 代码:
single {
val interceptor = HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger {
override fun log(message: String) {
Log.d("HttpLoggingInterceptor", message)
}
}).setLevel(HttpLoggingInterceptor.Level.BODY)
val okHttpClient = OkHttpClient.Builder()
.readTimeout(180, TimeUnit.SECONDS)
.writeTimeout(45, TimeUnit.SECONDS)
.hostnameVerifier { _: String?, _: SSLSession? -> true }
.addInterceptor(interceptor)
.build()
val retrofit = Retrofit.Builder()
.baseUrl("${Config.baseUrl}/")
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create(get()))
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build()
retrofit.create(IQuipsAuth::class.java)
}
您似乎想要两个不同的 OkHttpClient
。 IQuipsAuth
取决于哪个不使用 AccessTokenInterceptor
或 AccessTokenAuthenticator
(直接与 Auth 服务对话时你真的想要那些吗?)。另一个 OkHttpClient
将用于使用 IQuipsAuth
进行身份验证的其他服务。
您可以使用限定符区分同一类型的两个实例。下面是关于使用带有刀柄的限定符的片段:https://developer.android.com/training/dependency-injection/hilt-android#multiple-bindings
您可以使用 dagger.Lazy<T>
.
fun provideOkHttpClient (application: Application, iQuipsAuth: Lazy<IQuipsAuth>): OkHttpClient {
// ...
.addInterceptor(AccessTokenInterceptor(application, iQuipsAuth)) // pass lazy
.authenticator(AccessTokenAuthenticator(application, iQuipsAuth)) // pass lazy
// ...
}
然后在实际使用客户端时调用lazy.get()
。
请注意,如果 AccessTokenInterceptor
和 AccessTokenAuthenticator
都使用 @Inject constructor
提供给 Dagger,并提供给此 @Provides
方法,这将更加不言自明作为方法的参数。