Как добавить модернизированную базовую аутентификацию в сетевой модуль с рукоятью кинжала?
Я новичок в Котлине и использую рукоять кинжала для чистого кода.
Мне нужна базовая аутентификация во всех моих запросах, кроме запроса на вход, потому что токен поступает из. запрос на вход.
Мой вопрос в том, как я могу выполнить все свои запросы, кроме входа в систему, используя базовую аутентификацию с рукояткой кинжала?
Мой объект модуля выглядит так:
Любой совет или образец кода, пожалуйста:)
@Module
@InstallIn(ApplicationComponent::class)
object NetworkingModule {
@Provides
fun providesBaseUrl(): String {
return NetworkingConstants.BASE_URL
}
@Provides
fun providesLoggingInterceptor(): HttpLoggingInterceptor {
return HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY)
}
@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()
}
@Provides
fun provideRetrofitClient(okHttpClient: OkHttpClient, baseUrl: String, converterFactory: Converter.Factory): Retrofit {
return Retrofit.Builder()
.baseUrl(baseUrl)
.client(okHttpClient)
.addConverterFactory(converterFactory)
.build()
}
@Provides
fun provideRestApiService(retrofit: Retrofit): ApiService {
return retrofit.create(ApiService::class.java)
}
}
Я думаю, мне следует использовать BasicAuthInterceptor, но как я могу добавить это в модуль рукоятки?
1 ответ
Если вам нужно добавить еще один перехватчик для некоторых других запросов, это означает, что вам нужно предоставить разные реализации (несколько привязок) одного и того же типа.
Чтобы сообщить Hilt, как предоставлять разные реализации (несколько привязок) одного и того же типа, вы можете использовать квалификаторы.
Квалификатор - это аннотация, используемая для идентификации привязки. Если вам нужно добавить еще один перехватчик, реализовав интерфейс Intercepor, вы можете использовать аннотацию @Binds для функции внутри модуля Hilt.Но... вам нужно создать еще один модуль для использования @Binds.
Модули Hilt не могут содержать как нестатические, так и абстрактные методы привязки, поэтому вы не можете размещать аннотации @Binds и @Provides в одном классе.
Итак, ваш код должен быть примерно таким:
// ПЕРВЫЙ: определите четыре квалификатора в NetworkingModule для двух типов OkHttpClient и двух разных retrofitClient:
@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)
// }
}
Теперь нам нужно добавить AuthBasicInterceptor, который нам нужен для создания нового модуля с именем AuthInterceptorModule.kt и добавления к нему абстрактной функции bindAuthInterceptor типа Interceptor.
AuthInterceptorModule.kt
@InstallIn(ApplicationComponent::class)
@Module
abstract class AuthInterceptorModule {
@Binds
abstract fun bindAuthInterceptor(basicAuthInterceptor: AuthBasicInterceptor): Interceptor
}
и Создайте еще один класс с именем AuthBasicInterceptor.kt, реализующий Interceptor:
class AuthBasicInterceptor @Inject constructor() : Interceptor {
...
}
Все, все настроено. Теперь вы можете вводить retrofitClients в другие классы, например:
@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)
...
}
...
}