If you need to add another interceptor for some other requests, that means you need to provide different implementations (multiple bindings) of the same type
To tell Hilt how to provide different implementations (multiple bindings) of the same type, you can use qualifiers.
A qualifier is an annotation used to identify a binding.
If you need to add another interceptor by implementing Intercepor interface, you can use the @Binds annotation on a function inside a Hilt module.
But...
you need to create another module for using @Binds.
Hilt Modules cannot contain both non-static and abstract binding
methods, so you cannot place @Binds and @Provides annotations in the
same class.
So your code should be something like this:
//FIRST: define four qualifiers in the NetworkingModule for two types of OkHttpClient and two different retrofitClients:
@Module
@InstallIn(ApplicationComponent::class)
object NetworkingModule {
//FIRST: define four qualifiers in the NetworkingMoule
@Qualifier // define qualifier for LoginRetrofitClient
@Retention(AnnotationRetention.BINARY)
annotation class LoginRetrofitClient
@Qualifier // define qualifier for OtherRetrofitClient
@Retention(AnnotationRetention.BINARY)
annotation class OtherRetrofitClient
@Qualifier // define qualifier for LoginOkHttpClient
@Retention(AnnotationRetention.BINARY)
annotation class LoginOkHttpClient
@Qualifier // define qualifier for OtherOkHttpClient
@Retention(AnnotationRetention.BINARY)
annotation class OtherOkHttpClient
@Provides
fun providesBaseUrl(): String {
return NetworkingConstants.BASE_URL
}
// make sure add qualifier for LoginRetrofitClient
@LoggingInterceptor
@Provides
fun providesLoggingInterceptor(): HttpLoggingInterceptor {
return HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY)
}
// add @LoginOkHttpClient for providerOkHttpClient which we add AuthBasicInterceptorto to
@LoginOkHttpClient
@Provides
fun provideOkHttpClient(authBasicInterceptor: AuthBasicInterceptor): OkHttpClient {
val okHttpClient = OkHttpClient().newBuilder()
okHttpClient.callTimeout(40, TimeUnit.SECONDS)
okHttpClient.connectTimeout(40, TimeUnit.SECONDS)
okHttpClient.readTimeout(40, TimeUnit.SECONDS)
okHttpClient.writeTimeout(40, TimeUnit.SECONDS)
okHttpClient.addInterceptor(authBasicInterceptor)
okHttpClient.build()
return okHttpClient.build()
}
// add @OtherOkHttpClient for providerOkHttpClient which we add loggingInterceptor to
@OtherOkHttpClient
@Provides
fun provideOkHttpClient(loggingInterceptor: HttpLoggingInterceptor): OkHttpClient {
val okHttpClient = OkHttpClient().newBuilder()
okHttpClient.callTimeout(40, TimeUnit.SECONDS)
okHttpClient.connectTimeout(40, TimeUnit.SECONDS)
okHttpClient.readTimeout(40, TimeUnit.SECONDS)
okHttpClient.writeTimeout(40, TimeUnit.SECONDS)
okHttpClient.addInterceptor(loggingInterceptor)
okHttpClient.build()
return okHttpClient.build()
}
@Provides
fun provideConverterFactory(): Converter.Factory {
return GsonConverterFactory.create()
}
// make sure add qualifier for LoginRetrofitClient
@LoginRetrofitClient
@Provides
fun provideRetrofitClient(@LoginOkHttpClient okHttpClient: OkHttpClient, // Remember to add @LoginOkHttpClient qualifier to distinguish OkHttpClient dependencies
baseUrl: String, converterFactory: Converter.Factory): Retrofit {
return Retrofit.Builder()
.baseUrl(baseUrl)
.client(okHttpClient)
.addConverterFactory(converterFactory)
.build()
}
@OtherRetrofitClient
@Provides
fun provideRetrofitClient(@OtherOkHttpClient okHttpClient: OkHttpClient, // Remember to add @OtherOkHttpClient qualifier to distinguish OkHttpClient dependencies
baseUrl: String,
converterFactory: Converter.Factory): Retrofit {
return Retrofit.Builder()
.baseUrl(baseUrl)
.client(okHttpClient)
.addConverterFactory(converterFactory)
.build()
}
// also you need different flavors of ApiService by defining two more qualifiers for different retrofitClients which I commented that for simplicity
// @Provides
//fun provideRestApiService(retrofit: Retrofit): ApiService {
// return retrofit.create(ApiService::class.java)
// }
}
Now we need to add AuthBasicInterceptor, which we need to create a new module named AuthInterceptorModule.kt and add an
abstract bindAuthInterceptor function of the type Interceptor to it.
AuthInterceptorModule.kt
@InstallIn(ApplicationComponent::class)
@Module
abstract class AuthInterceptorModule {
@Binds
abstract fun bindAuthInterceptor(basicAuthInterceptor: AuthBasicInterceptor): Interceptor
}
and Create another class named AuthBasicInterceptor.kt implements Interceptor:
class AuthBasicInterceptor @Inject constructor() : Interceptor {
...
}
That's it, everything is set. Now you can Inject retrofitClients into other classes like:
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
@LoginRetrofitClient
@Inject lateinit var loginRetrofit: Retrofit
@OtherRetrofitClient
@Inject lateinit var otherRetrofit: Retrofit
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
...
}
...
}