Сервис ретрофита всегда нулевой после добавления Interceptor и внедрения его с помощью Dagger2 - PullRequest
1 голос
/ 09 апреля 2019

У меня есть relogin сервис модернизации, подобный этому

interface TokenService {
    @GET("re-login")
    fun relogin(): Call<ReloginResponse>
}

Затем у меня есть NetModule, где все зависимости вводятся как этот

@Module
class NetModule(baseUrl: String) {
    var baseUrl = baseUrl
    @Provides
    @Singleton
    fun provideGson(): Gson {
        val gsonBuilder = GsonBuilder()
        gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
        return gsonBuilder.create()
    }

    @Provides
    @Singleton
    fun provideOkhttp(tokenInterceptor: TokenInterceptor): OkHttpClient {

        val logging = HttpLoggingInterceptor()
        logging.setLevel(HttpLoggingInterceptor.Level.BODY)
        val client = OkHttpClient.Builder()
//                .authenticator(tokenAutheticator)
                .connectTimeout(60, TimeUnit.SECONDS)
                .writeTimeout(60, TimeUnit.SECONDS)
                .readTimeout(60, TimeUnit.SECONDS)
                .addInterceptor(logging)
                .addInterceptor(tokenInterceptor)

                .build()

        return client
    }

    @Provides
    @Singleton
    fun provideRetrofit(gson: Gson, okHttpClient: OkHttpClient): Retrofit {
        return Retrofit.Builder().addConverterFactory(GsonConverterFactory.create(gson))
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .baseUrl(baseUrl)
                .client(okHttpClient)
                .build()
    }
    @Provides
    @Singleton
    fun provideTokenHoler():TokenHolder{
        return TokenHolder()
    }
    @Provides
    @Singleton
    fun provideTokenService(retrofit: Retrofit,tokenHolder: TokenHolder):TokenService{
        val tokenService = retrofit.create(TokenService::class.java)
        tokenHolder.tokenService = tokenService
        return tokenService
    }

}

Тогда TokenHolder класскак это

class TokenHolder {
    var tokenService:TokenService?=null
        get() = field
        set(value) {field=value}
}

И это класс TokenInterceptor, где я получаю null в части TokenService.

@Singleton
class TokenInterceptor @Inject constructor(private val tokenHolder: TokenHolder) :Interceptor{
    var token:String=""
    override fun intercept(chain: Interceptor.Chain): Response {

        val original = chain.request()
        val originalHttpUrl = original.url()

        val url = originalHttpUrl.newBuilder()
                .addQueryParameter("token", token)
                .build()

        // Request customization: add request headers
        val requestBuilder = original.newBuilder()
                .url(url)

        val request = requestBuilder.build()
        val response = chain.proceed(request)

        if(response.code()==401){

            val newToken = tokenHolder.tokenService?.relogin()?.execute()?.body()?.token

            val url1 = originalHttpUrl.newBuilder()
                    .addQueryParameter("token", newToken)
                    .build()
            println("########## new new token ########## "+newToken)//this is null
            // Request customization: add request headers
            val requestBuilder1 = original.newBuilder()
                    .url(url1)

            val request1 = requestBuilder1.build()
            val response1 = chain.proceed(request1)
            return response1
        }

        return chain.proceed(request)
    }
}

Я пытаюсь нажать Relogin после того, как получаю401 ответ, но я всегда получаю TokenService ноль.Как я должен предоставить зависимости?Любая помощь будет оценена.Спасибо

1 Ответ

0 голосов
/ 09 апреля 2019

Насколько я вижу, TokenHolder имеет нулевой экземпляр TokenService, потому что нет способа передать его туда.Вы создаете экземпляр TokenService через Dagger и передаете его TokenHolder, но это не тот экземпляр, который вы получаете внутри перехватчика.Вы должны инвертировать ваши зависимости.Обновите методы модуля до этого и скажите мне, работает ли он.

@Provides
@Singleton
fun provideTokenHolder(service:TokenService): TokenHolder{
    return TokenHolder(service)
}

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

TokenService как ноль не должен произойти, поэтому вы должны объявить TokenHolder, как показано ниже.

class TokenHolder(val service: TokenService)

Более того, чтобы сломать вашу зависимостькруг.Вы должны изменить объявление TokenInterceptor.

class TokenInterceptor @Inject constructor(private val tokenHolder: Lazy<TokenHolder>) : Interceptor

Оберните TokenHolder с Dagger.Lazy, и он должен сделать свою работу.

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