Home > database >  Cannot set local variable value
Cannot set local variable value

Time:08-15

I am having a wierd problem.

@Singleton
class AppInterceptor @Inject constructor() : Interceptor {
    private var accessToken: String? = null
    fun setAccessToken(accessToken: String?) {
        this.accessToken = accessToken
        Log.d("Tag", "Access Setting: ${this.accessToken}")
    }

    override fun intercept(chain: Interceptor.Chain): Response {
        val request: Request = chain.request()
        val requestBuilder: Request.Builder = request.newBuilder()
        accessToken?.let { requestBuilder.addHeader("authorization", "Bearer $it") }

        return chain.proceed(requestBuilder.build())
    }
}

In the code above, after calling the setAccessToken(accessToken: String?) the first Log prints the right token, but the intercept function always gets accessToken = null. I have been struggling with this problem for hours. Does anyone know why I'm getting this issue?

To update the accessToken, I have injected the interceptor into a viewModel, then I called the setAccessToken function.

      @HiltViewModel
        class ApiViewModel @Inject constructor(
            private val apiHelper: APIHelper,
            private val oktaManager: OktaManager,
            private val interceptor: AppInterceptor
        ) : AndroidViewModel() {
        
            fun getResult() {
                viewModelScope.launch(Dispatchers.IO) {
                    interceptor.setAccessToken(oktaManager.gettingOktaToken())
                    try {
                        apiHelper.getResults()                   
                    } catch (e: Exception) {
                        Log.e("error", e.toString())
                    }
                }
            }    
        }

Here is the Retrofit builder

@Module
@InstallIn(SingletonComponent::class)
object RetrofitBuilder {


    private const val BASE_URL = "https://myUrl"

    private val interceptor = run {
        val httpLoggingInterceptor = HttpLoggingInterceptor()
        httpLoggingInterceptor.apply {
            httpLoggingInterceptor.level = HttpLoggingInterceptor.Level.BODY
        }
    }

    @Singleton
    @Provides
    fun provideOkHTTPClient(): OkHttpClient {
        return OkHttpClient.Builder()
            .addInterceptor(interceptor)
            .apply { addInterceptor(AppInterceptor()) }
            .addInterceptor(interceptor)
            .build()
    }

    @Singleton
    @Provides
    fun provideObjectMapper(): ObjectMapper {
        return jacksonObjectMapper().registerModule(JavaTimeModule())
            .configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
            .configure(SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS, false)
    }

    @Singleton
    @Provides
    fun provideRetrofitInstance(
        client: OkHttpClient,
        objectMapper: ObjectMapper
    ): Retrofit {
        return Retrofit.Builder()
            .client(client)
            .baseUrl(BASE_URL)
            .addConverterFactory(JacksonConverterFactory.create(objectMapper))
            .build()
    }

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

CodePudding user response:

One thing you can try is to set the data in Shared preference in AppViewModel and get that in intercept funtion. One thing needs to be validated is interceptor instance used by retrofit and viewmodel are same .As its singleton injection , the access token should updating the existing object. Not sure why its not working.

Update: You need add AppInterceptor injection in provideOkHttpClient() and use that object to addInterceptor()

   @Singleton
    @Provides
    fun provideOkHTTPClient(appInterceptor:AppInterceptor): OkHttpClient {
        return OkHttpClient.Builder()
            .addInterceptor(interceptor)
            .apply { addInterceptor(appInterceptor) }
            .addInterceptor(interceptor)
            .build()
    }
  • Related