Android Dagger2 + OkHttp + Retrofit с перехватчиком (для маркера обновления) ошибка цикла зависимости - PullRequest
1 голос
/ 09 мая 2019

У меня была «типичная» проблема ошибки цикла зависимости при попытке вызвать токен обновления в Interceptor. Я нашел несколько связанных вопросов и ответов, особенно этот один и этот один . Я последовал за ними, и он сделал код компиляции.

Но это не работает, потому что «ServiceHolder» всегда пуст (создается без службы), поэтому я думаю, что я делаю что-то не так с Dagger, и я не знаю, что.

У меня есть 'AuthServiceHolder':

class AuthServiceHolder {

    internal var authService: AuthService? = null

    fun get(): AuthService? {
        return authService
    }

    fun set(authService: AuthService) {
            this.authService = authService
    }
}

У меня есть 'TokenExpiredInterceptor' (первые строки):

@TokenExpiredInterceptorScope
class TokenExpiredInterceptor @Inject constructor(private val authServiceHolder: AuthServiceHolder
) : Interceptor

Я пытаюсь заставить службу выполнить вызов, но в TokenExpiredInterceptor она всегда пуста:

val authService = authServiceHolder.get()

У меня есть 2 экземпляра retroft, один для устаревшего API, а другой для нового API. Общий модуль:

@Module
object CommonApiModule {

    @JvmStatic
    internal fun retrofitBuilder(okHttpClient: OkHttpClient, baseUrl: HttpUrl) = Retrofit.Builder()
            .baseUrl(baseUrl)
            .client(okHttpClient)
(...)
}

Модуль, в котором я создаю модификацию для нового API:

@Module
class MyMicroservicesApiModule(baseUrl: String) : BaseApiModule(baseUrl) {
    @Provides
    @ForNetworkApi(NetworkApiType.MY_MICROSERVICES)
    @NetworkScope
    internal fun retrofit(okHttpClient: OkHttpClient,
                          callAdapterFactory: RxJava2CallAdapterFactory,
                          moshi: Moshi): Retrofit =
            CommonApiModule.retrofitBuilder(okHttpClient, httpUrl)
                    .addCallAdapterFactory(callAdapterFactory)
                    .addConverterFactory(MoshiConverterFactory.create(moshi))
                    .build()

}

Модуль с перехватчиком:

@Module(includes = [
    (...)
])
abstract class AuthTokenBindingsModule {

    @Binds
    @IntoSet
    @ForNetworkInterceptors
    internal abstract fun tokenExpiredInterceptor(tokenExpiredInterceptor: TokenExpiredInterceptor): Interceptor

    (...)

    @Module
    companion object {
        (...)
        @Provides
        @JvmStatic
        @NetworkScope
        fun authServiceHolder(): AuthServiceHolder = AuthServiceHolder()
    }
}

Модуль для создания httpClient:

@Module(includes = [HttpInterceptorsModule::class])
object HttpModule {
    private const val CONNECTION_TIMEOUT = 25
    private const val READ_CONNECTION_TIMEOUT = 25
    private const val WRITE_CONNECTION_TIMEOUT = 25

    private const val DISK_CACHE_SIZE: Long = 50 * 1024 * 1024

    @JvmStatic
    @Provides
    @NetworkScope
    internal fun httpClient(application: Application,
                            @ForNetworkInterceptors networkInterceptors: Set<@JvmSuppressWildcards Interceptor>,
                            @ForHttpInterceptors httpInterceptors: Set<@JvmSuppressWildcards Interceptor>): OkHttpClient {
        val builder = httpClientBuilder(application)
        httpInterceptors.forEach { it -> builder.addInterceptor(it) }
        networkInterceptors.forEach { it -> builder.addNetworkInterceptor(it) }

        if (BuildConfig.DEBUG) {
            val loggingInterceptor = HttpLoggingInterceptor()
            loggingInterceptor.level = HttpLoggingInterceptor.Level.BODY
            builder.addNetworkInterceptor(loggingInterceptor)
        }
        return builder.build()
    }

    @JvmStatic
    private fun httpClientBuilder(application: Application): OkHttpClient.Builder {
        val builder = OkHttpClient.Builder()
                .connectTimeout(CONNECTION_TIMEOUT.toLong(), TimeUnit.SECONDS)
                .readTimeout(READ_CONNECTION_TIMEOUT.toLong(), TimeUnit.SECONDS)
                .writeTimeout(WRITE_CONNECTION_TIMEOUT.toLong(), TimeUnit.SECONDS)

        val cacheDir = File(application.cacheDir, "http")
        val cache = Cache(cacheDir, DISK_CACHE_SIZE)
        builder.cache(cache)
        return builder
    }
}

Наконец, мой сетевой компонент:

@NetworkScope
@TokenExpiredInterceptorScope
@AuthenticatorScope
@Component(modules = [
    (...)
    CommonApiModule::class,
    MyMicroservicesApiModule::class,
    AuthTokenBindingsModule::class,
    (...)
], dependencies = [AppServiceProvider::class])
interface NetworkComponent :
        (...)
        MyMicroservicesApiProvider,
        (...) {

С этим кодом у меня есть экземпляр 'AuthServiceHolder' в 'TokenExpiredInterceptor', он НЕ является нулевым, но он пуст. Я видел в ссылках выше, я должен реорганизовать поставщика 'AuthService' что-то вроде этого:

    @Provides
    @NetworkScope
    internal fun authService(@ForNetworkApi(NetworkApiType.MY_MICROSERVICES) retrofit: Retrofit, authServiceHolder: AuthServiceHolder): AuthService {
        val authService = retrofit.create(AuthService::class.java)
        authServiceHolder.set(authService)
        return authService
    }`

Но я не знаю, где это поставить. Я пытался в AuthTokenBindingsModule, в MyMicroservicesApiModule, но безуспешно, он всегда пуст.

Я пропустил несколько строк кода, чтобы сделать его проще и для конфиденциальности.

Есть идеи? Заранее спасибо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...