如何摆脱这个令牌认证器 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)
    }

您似乎想要两个不同的 OkHttpClientIQuipsAuth 取决于哪个不使用 AccessTokenInterceptorAccessTokenAuthenticator(直接与 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()

请注意,如果 AccessTokenInterceptorAccessTokenAuthenticator 都使用 @Inject constructor 提供给 Dagger,并提供给此 @Provides 方法,这将更加不言自明作为方法的参数。