android - 如何使用匕首将改造基本身份验证添加到网络模块?
问题描述
我是 Kotlin 的新手,我正在使用 dagger hilt 来编写干净的代码。
我需要在除登录请求之外的所有请求中进行基本身份验证,因为令牌来自。登录请求。
我的问题是除了登录使用带有匕首刀柄的基本身份验证之外,我该如何完成我的所有请求?
我的模块对象是这样的:
请提供任何建议或示例代码:)
@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 但如何将其添加到 hilt 模块?
解决方案
如果您需要为其他一些请求添加另一个拦截器,这意味着您需要提供相同类型的不同实现(多个绑定)
要告诉 Hilt 如何提供相同类型的不同实现(多个绑定),您可以使用限定符。
限定符是用于标识绑定的注释。如果需要通过实现 Intercepor 接口来添加另一个拦截器,可以在 Hilt 模块内的函数上使用 @Binds 注解。 但是...... 您需要创建另一个模块来使用@Binds。
Hilt 模块不能同时包含非静态和抽象绑定方法,因此您不能将 @Binds 和 @Provides 注解放在同一个类中。
所以你的代码应该是这样的:
//FIRST:在 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 的新模块并向其添加类型为 Interceptor 的抽象 bindAuthInterceptor 函数。
AuthInterceptorModule.kt
@InstallIn(ApplicationComponent::class)
@Module
abstract class AuthInterceptorModule {
@Binds
abstract fun bindAuthInterceptor(basicAuthInterceptor: AuthBasicInterceptor): Interceptor
}
并创建另一个名为 AuthBasicInterceptor.kt 的类实现拦截器:
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)
...
}
...
}
推荐阅读
- java - 打印出从文件读取存储的数组数据
- reactjs - 将函数放入渲染方法会减慢我的应用程序
- javascript - 尝试在 React 中映射传递的对象属性数组
- wordpress - WordPress woo commerce Rest api 根据属性选项获取数据
- android - [已解决]在“推荐 Android Gradle 插件更新”后出现此错误:无法解析 com.android.support.constraint:constraint-layout:2.0.4
- python - 使用从 txt 文件 Matplotlib Python3 中提取的数据创建水平条形图
- php - php 错误:“试图访问 bool 类型值的数组偏移量”
- python - send_mail() 为参数“fail_silently”获取多个值 Django 联系表单仅传递消息而不是名称或主题
- java - 使用仅在 MainActivity 上工作的“区域设置”以编程方式更改语言。如何在所有活动中更改语言
- javascript - 来自导入函数的“未定义”值,需要在 React 应用程序中使用