Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

209
Visualizações
Dagger + Retrofit. Adding auth headers at runtime

I'm wondering if there is a way for Dagger to know that it should recreate an object when new data is available.

The instance I am speaking of is with the request headers I have for retrofit. At some point (when the user logs in) I get a token that I need to add to the headers of retrofit to make authenticated requests. The issue is, I'm left with the same unauthenticated version of retrofit. Here's my injection code:

@Provides
    @Singleton
    OkHttpClient provideOkHttpClient(Cache cache) {
        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        OkHttpClient client = new OkHttpClient.Builder()
                .addInterceptor(interceptor)
                .cache(cache).build();
         client
                .newBuilder()
                .addInterceptor(
                    chain -> {
                        Request original = chain.request();
                        Request.Builder requestBuilder = original.newBuilder()
                                .addHeader("Accept", "Application/JSON");
                        Request request = requestBuilder.build();
                        return chain.proceed(request);
                    }).build();
        return client;
    }

  @Provides
    @Singleton
    Retrofit provideRetrofit(Gson gson, OkHttpClient okHttpClient) { 
        Retrofit retrofit = new Retrofit.Builder()
                .addConverterFactory(GsonConverterFactory.create(gson))
                .addCallAdapterFactory(RxErrorHandlingCallAdapterFactory.create())
                .baseUrl(mBaseUrl)
                .client(okHttpClient)
                .build();
        return retrofit;
}

@Provides
    @Singleton
    public NetworkService providesNetworkService(Retrofit retrofit) {
        return retrofit.create(NetworkService.class);
    }

Any ideas on how to make this work?

about 4 years ago · Santiago Trujillo
3 Respostas
Responde à pergunta

0

I personally created an okhttp3.Interceptor that does that for me, which I update once I have the required token. It looks something like:

@Singleton
public class MyServiceInterceptor implements Interceptor {
  private String sessionToken;

  @Inject public MyServiceInterceptor() {
  }

  public void setSessionToken(String sessionToken) {
    this.sessionToken = sessionToken;
  }

  @Override public Response intercept(Chain chain) throws IOException {
    Request request = chain.request();

    Request.Builder requestBuilder = request.newBuilder();

    if (request.header(NO_AUTH_HEADER_KEY) == null) {
      // needs credentials
      if (sessionToken == null) {
        throw new RuntimeException("Session token should be defined for auth apis");
      } else {
        requestBuilder.addHeader("Cookie", sessionToken);
      }
    }

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

In the corresponding dagger component, I expose this interceptor so I can set the sessionToken when I need to.

That is some stuff that Jake talked about it his talk Making Retrofit Work For You.

about 4 years ago · Santiago Trujillo Relatório

0

Please consider using the approach mentioned by @oldergod as it is the "official" and much better way, whereas the approaches mentioned below are not advised, they may be considered as workarounds.


You have a couple of options.

  1. As soon as you get the token, you have to null out the component that provided you the Retrofit instance, create a new component and ask for a new Retrofit instance, which will be instantiated with necessary okhttp instance.
  2. A fast and bad one - Save the token in SharedPreferences, create okHttp header, which will apply token reading from SharedPreferences. If there is none - send no token header.
  3. Even uglier solution - declare a static volatile String field, and do the same thing like in step 2.

Why the second option is bad? Because on each request you would be polling disk and fetch data from there.

about 4 years ago · Santiago Trujillo Relatório

0

Created custom RequestInterceptor with @Inject constructor

RequestInterceptor

@Singleton
class
RequestInterceptor @Inject constructor(
    private val preferencesHelper: PreferencesHelper,
) : Interceptor {

    @Throws(IOException::class)
    override fun intercept(chain: Interceptor.Chain): Response {
        var newRequest: Request = chain.request()

        newRequest = newRequest.newBuilder()
            .addHeader(
                "AccessToken",
                preferencesHelper.getAccessTokenFromPreference()
            )
            .build()


        Log.d(
            "OkHttp", String.format(
                "--> Sending request %s on %s%n%s",
                newRequest.url(),
                chain.connection(),
                newRequest.headers()
            )
        );
        return chain.proceed(newRequest)

  }

ApplicationModule

@Module(includes = [AppUtilityModule::class])
class ApplicationModule(private val application: AppController) {

    @Provides
    @Singleton
    fun provideApplicationContext(): Context = application

    @Singleton
    @Provides
    fun provideSharedPreferences(): SharedPreferences =
        PreferenceManager.getDefaultSharedPreferences(application.applicationContext)

}

PreferencesHelper

@Singleton
class PreferencesHelper
@Inject constructor(
    private val context: Context,
    private val sharedPreferences: SharedPreferences
) {
    private val PREF_KEY_ACCESS_TOKEN = "PREF_KEY_ACCESS_TOKEN"


    fun getAccessTokenFromPreference(): String? {
        return sharedPreferences.getString(PREF_KEY_ACCESS_TOKEN, null)
    }

}
about 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda