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?
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.
Retrofit
instance, create a new component and ask for a newRetrofit
instance, which will be instantiated with necessaryokhttp
instance.SharedPreferences
, createokHttp
header, which will apply token reading fromSharedPreferences
. If there is none - send no token header.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 SD card and fetch data from there.
Based on @oldergod solution kotlin version with different classes and structure
Make Retrofit instance like this
Add
ServiceInterceptor
class like belowLogin Interface and data class implementation
call this in any activity like this
Created custom RequestInterceptor with @Inject constructor
RequestInterceptor
ApplicationModule
PreferencesHelper
I personally created an
okhttp3.Interceptor
that does that for me, which I update once I have the required token. It looks something like: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.
Well tested and working
Earlier I was wondering, if session expires and user login again, will this interceptor replace the existing auth, but fortunately it is working fine.