Как выполнить синхронный вызов токена обновления внутри метода authenticate AuthenticationInterceptor без циклической зависимости Dagger2? - PullRequest
0 голосов
/ 06 июля 2019

Я хочу добавить вызов токена обновления в моем методе authenticate HttpAuthenticationInterceptor для управления истечением access_token для unAuthorized ответа 401.

Я добавил синхронный вызов refresh_token в методе authenticate с использованием интерфейса serviceClient (serviceGateway) retrofit 2.но я сталкиваюсь с проблемой циклической зависимости при введении serviceGateway в перехватчик.Нужно ли создавать отдельный интерфейс ServiceClient для этого вызова токена обновления?

Вот мои классы AuthenticationInterceptor и NetworkModule

class AuthenticationInterceptor @Inject constructor(private val preferences: SharedPreferencesKeyValueDataSource, private val serviceGateway: ServiceGateway) : Interceptor, Authenticator{

    @Throws(IOException::class)
    override fun authenticate(route: Route?, response: Response): Request?{
        if (response.code() == 401) {
            val credentials = Credentials.basic("dummy", "dummy")
            val refreshCall = serviceGateway.refreshToken(credentials, preferences.getValue(Constants.REFRESH_TOKEN, ""))

            //make it as retrofit synchronous call
            val refreshResponse = refreshCall.execute()
            return if (refreshResponse.code() == 200) {
                //Save the access token and refresh token in preferences
                refreshResponse.body()?.let{
                    preferences.setValue(Constants.ACCESS_TOKEN, it.access_token)
                    preferences.setValue(Constants.REFRESH_TOKEN, it.refresh_token)
                }
                val newAccessToken = refreshResponse.body()?.access_token
                response.request().newBuilder()
                        .header(AuthenticationInterceptor.AUTHORIZATION, "Bearer $newAccessToken")
                        .build()
            } else {
                null
            }
        }
        return null
    }
}

// А код из NetworkModule приведен ниже,

@Provides
    @Singleton
    fun provideAuthenticationInterceptor(preferences: SharedPreferencesKeyValueDataSource, serviceGateway: ServiceGateway) = AuthenticationInterceptor(preferences, serviceGateway)

    @Provides
    @Singleton
    fun provideOkhttpClient(loggingInterceptor: HttpLoggingInterceptor,
                            authenticationInterceptor: AuthenticationInterceptor): OkHttpClient {

        val client = OkHttpClient.Builder()
        client.addInterceptor(loggingInterceptor)
        client.addInterceptor(authenticationInterceptor)
        client.authenticator(authenticationInterceptor)
        client.connectTimeout(15, TimeUnit.SECONDS)
        client.readTimeout(20, TimeUnit.SECONDS)
        return client.build()
    }


    @Provides
    @Singleton
    fun provideRetrofit(gson: Gson, okHttpClient: OkHttpClient,
                        @Named("BASE_URL_CORE") baseUrl: String)
            : Retrofit {

        return Retrofit.Builder()
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create(gson))
                .baseUrl(baseUrl)
                .client(okHttpClient)
                .build()
    }

    @Provides
    @Singleton
    fun provideGateway(retrofit: Retrofit): ServiceGateway {
        return retrofit.create(ServiceGateway::class.java)
    }

Ошибка компилятора ...

  • ServiceGateway вводится в ... NetworkModule.provideAuthenticationInterceptor (…, serviceGateway)
  • AuthenticationInterceptor вводится в
    ...NetworkModule.provideOkhttpClient (…, authenticationInterceptor)
  • okhttp3.OkHttpClient внедряется в ... NetworkModule.provideRetrofit (…, okHttpClient,…)
  • retrofit2.Retrofogger at injected.provideGateway (дооснащение)

1 Ответ

0 голосов
/ 07 июля 2019

Я попробовал Dagger Lazy Injection (import daggger.Lazy) для ServiceGateway, и он работает нормально, без циклической зависимости Dagger.

class AuthenticationInterceptor @Inject constructor(private val preferences: SharedPreferencesKeyValueDataSource, private val serviceGateway: Lazy<ServiceGateway>) : Interceptor, Authenticator{
}

API-интерфейс RefreshToken вызывает сейчас, но это приводит к другой проблеме (циклический вызов токена обновления ).Поэтому, чтобы решить эту проблему с циклическим вызовом обновления токена, лучше сделать отдельный serviceGateway для вызова обновления токена, как это, ребята Ясин Качмаз ответил здесь .Другое решение состоит в том, чтобы сделать вызов с обновлением токена напрямую через Okhttp (без использования интерфейса службы Retrofit)

Спасибо Аамир Абро за помощь в решении этой проблемы.

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