How to solve error: [Dagger/MissingBinding] while working With Retrofit with Dagger2
How to solve error: [Dagger/MissingBinding] while working With Retrofit with Dagger2
为了学习,我想在一个简单的项目中实现Dagger2 for Dependency Injection。我通读了 google Codelab 代码示例,以了解 Dagger2 的基本概念。然后我阅读了一些媒体博客和示例 Github repo,它已经在项目中实现了 Dagger2 以进行依赖注入。然后我开始了一个演示项目并尝试用 Retrofit 实现 Dagger2。实施后,我收到了一个意外的构建失败错误,其中 "error: [Dagger/MissingBinding] com.aomi.mybase.data.remote.testimonial.TestimonialRestService cannot be provided without an @Provides-annotated method." TestimonialService 是 Api 相关服务。因此,我无法使用 @Provide 或 @Binds 注释进行注释。我真的不知道该怎么做才能解决这个问题
错误日志截图如下
https://imgur.com/a/0qQXLbN
让我分享一些我的代码,这样你就可以看看问题到底出在哪里
Qualifier.kt
@Qualifier
@MustBeDocumented
@Retention(RUNTIME)
annotation class Type(val type: String = "")
InterceptorModule.kt
@Module
class InterceptorModule {
@Module
companion object {
@JvmStatic
@Singleton
@Provides
fun provideLoggingInterceptor(): HttpLoggingInterceptor {
return HttpLoggingInterceptor().apply {
level = if (BuildConfig.DEBUG) BODY else NONE
}
}
@JvmStatic
@Singleton
@Type("Basic")
@Provides
fun provideBasicInterceptor(): Interceptor {
val basicAuthCredential = Credentials.basic(
"username",
"password"
)
try {
return Interceptor {
val request = it.request()
it.proceed(
request.newBuilder()
.header("Accept", "application/json")
.header("Content-Type", "application/json")
.header("Authorization", basicAuthCredential)
.build()
)
}
} catch (exception: Exception) {
throw Exception(exception.message)
}
}
@JvmStatic
@Singleton
@Type("Bearer")
@Provides
fun provideAuthInterceptor(appContext: Context): Interceptor {
val accessToken = AppPreferenceImpl(appContext).accessToken
try {
return Interceptor {
val request = it.request()
it.proceed(
request.newBuilder()
.header("Accept", "application/json")
.header("Content-Type", "application/json")
.header("Authorization", "Bearer $accessToken")
.build()
)
}
} catch (exception: Exception) {
throw Exception(exception.message)
}
}
}
}
NetworkModule.kt
@Module(
includes = [
InterceptorModule::class
]
)
abstract class NetworkModule {
@Module
companion object {
private const val BASE_URL = BuildConfig.BASE_URL
private const val TIME_OUT = 60L
@JvmStatic
@Singleton
@Type("Basic")
@Provides
fun provideBasicRetrofit(okHttpClient: OkHttpClient): Retrofit {
return Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.client(okHttpClient)
.callbackExecutor { Logger.d("returning") }
.build()
}
@JvmStatic
@Singleton
@Type("Basic")
@Provides
fun provideBasicOkHttpClient(loggingInterceptor: HttpLoggingInterceptor, basicInterceptor: Interceptor): OkHttpClient {
return OkHttpClient.Builder()
.connectTimeout(TIME_OUT, SECONDS)
.readTimeout(TIME_OUT, SECONDS)
.writeTimeout(TIME_OUT, SECONDS)
.addInterceptor(loggingInterceptor)
.addInterceptor(basicInterceptor)
.build()
}
@JvmStatic
@Singleton
@Type("Bearer")
@Provides
fun provideBearerRetrofit(okHttpClient: OkHttpClient): Retrofit {
return Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.client(okHttpClient)
.callbackExecutor { Logger.d("returning") }
.build()
}
@JvmStatic
@Singleton
@Type("Bearer")
@Provides
fun provideBearerOkHttpClient(loggingInterceptor: HttpLoggingInterceptor, authInterceptor: Interceptor): OkHttpClient {
return OkHttpClient.Builder()
.connectTimeout(TIME_OUT, SECONDS)
.readTimeout(TIME_OUT, SECONDS)
.writeTimeout(TIME_OUT, SECONDS)
.addInterceptor(loggingInterceptor)
.addInterceptor(authInterceptor)
// .authenticator(ServiceAuthenticator())
.build()
}
}
}
ServiceModule.kt
@Module
abstract class ServiceModule {
@Module
companion object {
@JvmStatic
@Singleton
@Type("Basic")
@Provides
fun provideTestimonialService(retrofit: Retrofit): TestimonialRestService {
return retrofit.create(TestimonialRestService::class.java)
}
}
}
RepositoryModule.kt
@Module
abstract class RepositoryModule {
@Binds
abstract fun provideTestimonialRepository(repo: TestimonialRepositoryImpl): TestimonialRepository
}
TestimonialRepository.kt
interface TestimonialRepository {
fun getTestimonials(): Flowable<ArrayList<Testimonial>>
}
TestimonialRepositoryImpl.kt
class TestimonialRepositoryImpl @Inject constructor(
private val testimonialDataSource: TestimonialDataSource
) : TestimonialRepository {
override fun getTestimonials(): Flowable<ArrayList<Testimonial>> {
return testimonialDataSource.getTestimonialResponse().map { it.testimonialList }
}
}
TestimonialDataSource.kt
class TestimonialDataSource @Inject constructor(
private val testimonialRestService: TestimonialRestService
) {
fun getTestimonialResponse(): Flowable<TestimonialResponse> {
return testimonialRestService.getTestimonialResponse().onResponse()
}
}
TestimonialRestService.kt
interface TestimonialRestService {
@GET("static/testimonials")
fun getTestimonialResponse(): Flowable<Response<TestimonialResponse>>
}
WelcomeViewModel.kt
class WelcomeViewModel @Inject constructor(
private val repository: TestimonialRepository
) : BaseViewModel() {
var testimonials = MutableLiveData<ArrayList<Testimonial>>()
fun getTestimonials() {
if(testimonials.value == null) {
compositeDisposable += repository.getTestimonials()
.performOnBackgroundOutputOnMain()
.doOnSubscribe { loader.value = true }
.doAfterTerminate { loader.value = false }
.subscribe({
Logger.d(it)
testimonials.value = it
}, {
handleException(it)
})
}
}
}
使用限定符时,需要在两个地方放置限定符注解:
- 对象的绑定位置:
@Binds
或 @Provides
方法,构建器中的 @BindsInstance
方法,或工厂中的 @BindsInstance
参数。
- 对象的使用位置:参数到
@Binds
或@Provides
方法,@Inject
构造函数或方法的参数, 或 @Inject
field/property.
仅当使用站点的限定符与 @Binds
/@Provides
方法上的限定符匹配时,才能提供依赖项。为此,"no qualifier" 是一种限定符。
既然你想用一个@Type("Basic")
限定的Retrofit
来提供一个非限定的TestimonialRestService
,这意味着参数应该是限定的,而方法本身应该是非限定的:
@JvmStatic
@Singleton
@Provides
fun provideTestimonialService(@Type("Basic") retrofit: Retrofit): TestimonialRestService {
return retrofit.create(TestimonialRestService::class.java)
}
修复此问题后,您会注意到 provideXxxRetrofit
方法也有错误,原因相同:它们都在寻找不合格的 OkHttpClient
,但唯一的 OkHttpClient
图中的绑定具有限定符。这些错误可以用同样的方式修复:
@JvmStatic
@Singleton
@Type("Basic")
@Provides
fun provideBasicRetrofit(@Type("Basic") okHttpClient: OkHttpClient): Retrofit {
return Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.client(okHttpClient)
.callbackExecutor { Logger.d("returning") }
.build()
}
虽然@Nitrodon的回答是对的,但是我根据他的回答做了更符合实际的,这样任何陷入这个问题的人都可以很容易地理解它。下面是更好理解的代码
Constant.kt
object Network {
const val BASIC = "Basic"
const val BEARER = "Bearer"
}
Qualifier.kt
@Qualifier
@MustBeDocumented
@Retention(RUNTIME)
annotation class InterceptorType(val type: String = "")
@Qualifier
@MustBeDocumented
@Retention(RUNTIME)
annotation class OkHttpClientType(val type: String = "")
@Qualifier
@MustBeDocumented
@Retention(RUNTIME)
annotation class RetrofitType(val type: String = "")
InterceptorModule.kt
@Module
class InterceptorModule {
companion object {
@Singleton
@Provides
fun provideLoggingInterceptor(): HttpLoggingInterceptor {
return HttpLoggingInterceptor().apply {
level = if (BuildConfig.DEBUG) BODY else NONE
}
}
@Singleton
@InterceptorType(BASIC)
@Provides
fun provideBasicInterceptor(): Interceptor {
val basicAuthCredential = Credentials.basic(
"ct_android",
"$2y$12$ej.DK5rJIZjF9FokTWErDeDylA7N.4apw0FZ2FllcK53KEYZqDryO"
)
try {
return Interceptor {
val request = it.request()
it.proceed(
request.newBuilder()
.header("Accept", "application/json")
.header("Content-Type", "application/json")
.header("Authorization", basicAuthCredential)
.build()
)
}
} catch (exception: Exception) {
throw Exception(exception.message)
}
}
@Singleton
@InterceptorType(BEARER)
@Provides
fun provideAuthInterceptor(appContext: Context): Interceptor {
val accessToken = AppPreferenceImpl(appContext).accessToken
try {
return Interceptor {
val request = it.request()
it.proceed(
request.newBuilder()
.header("Accept", "application/json")
.header("Content-Type", "application/json")
.header("Authorization", "Bearer $accessToken")
.build()
)
}
} catch (exception: Exception) {
throw Exception(exception.message)
}
}
}
}
NetworkModule.kt
@Module(
includes = [
InterceptorModule::class
]
)
abstract class NetworkModule {
companion object {
private const val BASE_URL = BuildConfig.BASE_URL
private const val TIME_OUT = 60L
@Singleton
@RetrofitType(BASIC)
@Provides
fun provideBasicRetrofit(@OkHttpClientType(BASIC) okHttpClient: OkHttpClient): Retrofit {
return Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.client(okHttpClient)
.callbackExecutor { Logger.d("returning") }
.build()
}
@Singleton
@OkHttpClientType(BASIC)
@Provides
fun provideBasicOkHttpClient(loggingInterceptor: HttpLoggingInterceptor, @InterceptorType(BASIC) basicInterceptor: Interceptor): OkHttpClient {
return OkHttpClient.Builder()
.connectTimeout(TIME_OUT, SECONDS)
.readTimeout(TIME_OUT, SECONDS)
.writeTimeout(TIME_OUT, SECONDS)
.addInterceptor(loggingInterceptor)
.addInterceptor(basicInterceptor)
.build()
}
@Singleton
@RetrofitType(BEARER)
@Provides
fun provideBearerRetrofit(@OkHttpClientType(BEARER) okHttpClient: OkHttpClient): Retrofit {
return Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.client(okHttpClient)
.callbackExecutor { Logger.d("returning") }
.build()
}
@Singleton
@OkHttpClientType(BEARER)
@Provides
fun provideBearerOkHttpClient(loggingInterceptor: HttpLoggingInterceptor, @InterceptorType(BEARER) authInterceptor: Interceptor): OkHttpClient {
return OkHttpClient.Builder()
.connectTimeout(TIME_OUT, SECONDS)
.readTimeout(TIME_OUT, SECONDS)
.writeTimeout(TIME_OUT, SECONDS)
.addInterceptor(loggingInterceptor)
.addInterceptor(authInterceptor)
// .authenticator(ServiceAuthenticator())
.build()
}
}
}
ServiceModule.kt
@Module
abstract class ServiceModule {
companion object {
@Singleton
@Provides
fun provideTestimonialService(@RetrofitType(BASIC) retrofit: Retrofit): TestimonialRestService {
return retrofit.create(TestimonialRestService::class.java)
}
}
}
为了学习,我想在一个简单的项目中实现Dagger2 for Dependency Injection。我通读了 google Codelab 代码示例,以了解 Dagger2 的基本概念。然后我阅读了一些媒体博客和示例 Github repo,它已经在项目中实现了 Dagger2 以进行依赖注入。然后我开始了一个演示项目并尝试用 Retrofit 实现 Dagger2。实施后,我收到了一个意外的构建失败错误,其中 "error: [Dagger/MissingBinding] com.aomi.mybase.data.remote.testimonial.TestimonialRestService cannot be provided without an @Provides-annotated method." TestimonialService 是 Api 相关服务。因此,我无法使用 @Provide 或 @Binds 注释进行注释。我真的不知道该怎么做才能解决这个问题
错误日志截图如下 https://imgur.com/a/0qQXLbN
让我分享一些我的代码,这样你就可以看看问题到底出在哪里
Qualifier.kt
@Qualifier
@MustBeDocumented
@Retention(RUNTIME)
annotation class Type(val type: String = "")
InterceptorModule.kt
@Module
class InterceptorModule {
@Module
companion object {
@JvmStatic
@Singleton
@Provides
fun provideLoggingInterceptor(): HttpLoggingInterceptor {
return HttpLoggingInterceptor().apply {
level = if (BuildConfig.DEBUG) BODY else NONE
}
}
@JvmStatic
@Singleton
@Type("Basic")
@Provides
fun provideBasicInterceptor(): Interceptor {
val basicAuthCredential = Credentials.basic(
"username",
"password"
)
try {
return Interceptor {
val request = it.request()
it.proceed(
request.newBuilder()
.header("Accept", "application/json")
.header("Content-Type", "application/json")
.header("Authorization", basicAuthCredential)
.build()
)
}
} catch (exception: Exception) {
throw Exception(exception.message)
}
}
@JvmStatic
@Singleton
@Type("Bearer")
@Provides
fun provideAuthInterceptor(appContext: Context): Interceptor {
val accessToken = AppPreferenceImpl(appContext).accessToken
try {
return Interceptor {
val request = it.request()
it.proceed(
request.newBuilder()
.header("Accept", "application/json")
.header("Content-Type", "application/json")
.header("Authorization", "Bearer $accessToken")
.build()
)
}
} catch (exception: Exception) {
throw Exception(exception.message)
}
}
}
}
NetworkModule.kt
@Module(
includes = [
InterceptorModule::class
]
)
abstract class NetworkModule {
@Module
companion object {
private const val BASE_URL = BuildConfig.BASE_URL
private const val TIME_OUT = 60L
@JvmStatic
@Singleton
@Type("Basic")
@Provides
fun provideBasicRetrofit(okHttpClient: OkHttpClient): Retrofit {
return Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.client(okHttpClient)
.callbackExecutor { Logger.d("returning") }
.build()
}
@JvmStatic
@Singleton
@Type("Basic")
@Provides
fun provideBasicOkHttpClient(loggingInterceptor: HttpLoggingInterceptor, basicInterceptor: Interceptor): OkHttpClient {
return OkHttpClient.Builder()
.connectTimeout(TIME_OUT, SECONDS)
.readTimeout(TIME_OUT, SECONDS)
.writeTimeout(TIME_OUT, SECONDS)
.addInterceptor(loggingInterceptor)
.addInterceptor(basicInterceptor)
.build()
}
@JvmStatic
@Singleton
@Type("Bearer")
@Provides
fun provideBearerRetrofit(okHttpClient: OkHttpClient): Retrofit {
return Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.client(okHttpClient)
.callbackExecutor { Logger.d("returning") }
.build()
}
@JvmStatic
@Singleton
@Type("Bearer")
@Provides
fun provideBearerOkHttpClient(loggingInterceptor: HttpLoggingInterceptor, authInterceptor: Interceptor): OkHttpClient {
return OkHttpClient.Builder()
.connectTimeout(TIME_OUT, SECONDS)
.readTimeout(TIME_OUT, SECONDS)
.writeTimeout(TIME_OUT, SECONDS)
.addInterceptor(loggingInterceptor)
.addInterceptor(authInterceptor)
// .authenticator(ServiceAuthenticator())
.build()
}
}
}
ServiceModule.kt
@Module
abstract class ServiceModule {
@Module
companion object {
@JvmStatic
@Singleton
@Type("Basic")
@Provides
fun provideTestimonialService(retrofit: Retrofit): TestimonialRestService {
return retrofit.create(TestimonialRestService::class.java)
}
}
}
RepositoryModule.kt
@Module
abstract class RepositoryModule {
@Binds
abstract fun provideTestimonialRepository(repo: TestimonialRepositoryImpl): TestimonialRepository
}
TestimonialRepository.kt
interface TestimonialRepository {
fun getTestimonials(): Flowable<ArrayList<Testimonial>>
}
TestimonialRepositoryImpl.kt
class TestimonialRepositoryImpl @Inject constructor(
private val testimonialDataSource: TestimonialDataSource
) : TestimonialRepository {
override fun getTestimonials(): Flowable<ArrayList<Testimonial>> {
return testimonialDataSource.getTestimonialResponse().map { it.testimonialList }
}
}
TestimonialDataSource.kt
class TestimonialDataSource @Inject constructor(
private val testimonialRestService: TestimonialRestService
) {
fun getTestimonialResponse(): Flowable<TestimonialResponse> {
return testimonialRestService.getTestimonialResponse().onResponse()
}
}
TestimonialRestService.kt
interface TestimonialRestService {
@GET("static/testimonials")
fun getTestimonialResponse(): Flowable<Response<TestimonialResponse>>
}
WelcomeViewModel.kt
class WelcomeViewModel @Inject constructor(
private val repository: TestimonialRepository
) : BaseViewModel() {
var testimonials = MutableLiveData<ArrayList<Testimonial>>()
fun getTestimonials() {
if(testimonials.value == null) {
compositeDisposable += repository.getTestimonials()
.performOnBackgroundOutputOnMain()
.doOnSubscribe { loader.value = true }
.doAfterTerminate { loader.value = false }
.subscribe({
Logger.d(it)
testimonials.value = it
}, {
handleException(it)
})
}
}
}
使用限定符时,需要在两个地方放置限定符注解:
- 对象的绑定位置:
@Binds
或@Provides
方法,构建器中的@BindsInstance
方法,或工厂中的@BindsInstance
参数。 - 对象的使用位置:参数到
@Binds
或@Provides
方法,@Inject
构造函数或方法的参数, 或@Inject
field/property.
仅当使用站点的限定符与 @Binds
/@Provides
方法上的限定符匹配时,才能提供依赖项。为此,"no qualifier" 是一种限定符。
既然你想用一个@Type("Basic")
限定的Retrofit
来提供一个非限定的TestimonialRestService
,这意味着参数应该是限定的,而方法本身应该是非限定的:
@JvmStatic
@Singleton
@Provides
fun provideTestimonialService(@Type("Basic") retrofit: Retrofit): TestimonialRestService {
return retrofit.create(TestimonialRestService::class.java)
}
修复此问题后,您会注意到 provideXxxRetrofit
方法也有错误,原因相同:它们都在寻找不合格的 OkHttpClient
,但唯一的 OkHttpClient
图中的绑定具有限定符。这些错误可以用同样的方式修复:
@JvmStatic
@Singleton
@Type("Basic")
@Provides
fun provideBasicRetrofit(@Type("Basic") okHttpClient: OkHttpClient): Retrofit {
return Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.client(okHttpClient)
.callbackExecutor { Logger.d("returning") }
.build()
}
虽然@Nitrodon的回答是对的,但是我根据他的回答做了更符合实际的,这样任何陷入这个问题的人都可以很容易地理解它。下面是更好理解的代码
Constant.kt
object Network {
const val BASIC = "Basic"
const val BEARER = "Bearer"
}
Qualifier.kt
@Qualifier
@MustBeDocumented
@Retention(RUNTIME)
annotation class InterceptorType(val type: String = "")
@Qualifier
@MustBeDocumented
@Retention(RUNTIME)
annotation class OkHttpClientType(val type: String = "")
@Qualifier
@MustBeDocumented
@Retention(RUNTIME)
annotation class RetrofitType(val type: String = "")
InterceptorModule.kt
@Module
class InterceptorModule {
companion object {
@Singleton
@Provides
fun provideLoggingInterceptor(): HttpLoggingInterceptor {
return HttpLoggingInterceptor().apply {
level = if (BuildConfig.DEBUG) BODY else NONE
}
}
@Singleton
@InterceptorType(BASIC)
@Provides
fun provideBasicInterceptor(): Interceptor {
val basicAuthCredential = Credentials.basic(
"ct_android",
"$2y$12$ej.DK5rJIZjF9FokTWErDeDylA7N.4apw0FZ2FllcK53KEYZqDryO"
)
try {
return Interceptor {
val request = it.request()
it.proceed(
request.newBuilder()
.header("Accept", "application/json")
.header("Content-Type", "application/json")
.header("Authorization", basicAuthCredential)
.build()
)
}
} catch (exception: Exception) {
throw Exception(exception.message)
}
}
@Singleton
@InterceptorType(BEARER)
@Provides
fun provideAuthInterceptor(appContext: Context): Interceptor {
val accessToken = AppPreferenceImpl(appContext).accessToken
try {
return Interceptor {
val request = it.request()
it.proceed(
request.newBuilder()
.header("Accept", "application/json")
.header("Content-Type", "application/json")
.header("Authorization", "Bearer $accessToken")
.build()
)
}
} catch (exception: Exception) {
throw Exception(exception.message)
}
}
}
}
NetworkModule.kt
@Module(
includes = [
InterceptorModule::class
]
)
abstract class NetworkModule {
companion object {
private const val BASE_URL = BuildConfig.BASE_URL
private const val TIME_OUT = 60L
@Singleton
@RetrofitType(BASIC)
@Provides
fun provideBasicRetrofit(@OkHttpClientType(BASIC) okHttpClient: OkHttpClient): Retrofit {
return Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.client(okHttpClient)
.callbackExecutor { Logger.d("returning") }
.build()
}
@Singleton
@OkHttpClientType(BASIC)
@Provides
fun provideBasicOkHttpClient(loggingInterceptor: HttpLoggingInterceptor, @InterceptorType(BASIC) basicInterceptor: Interceptor): OkHttpClient {
return OkHttpClient.Builder()
.connectTimeout(TIME_OUT, SECONDS)
.readTimeout(TIME_OUT, SECONDS)
.writeTimeout(TIME_OUT, SECONDS)
.addInterceptor(loggingInterceptor)
.addInterceptor(basicInterceptor)
.build()
}
@Singleton
@RetrofitType(BEARER)
@Provides
fun provideBearerRetrofit(@OkHttpClientType(BEARER) okHttpClient: OkHttpClient): Retrofit {
return Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.client(okHttpClient)
.callbackExecutor { Logger.d("returning") }
.build()
}
@Singleton
@OkHttpClientType(BEARER)
@Provides
fun provideBearerOkHttpClient(loggingInterceptor: HttpLoggingInterceptor, @InterceptorType(BEARER) authInterceptor: Interceptor): OkHttpClient {
return OkHttpClient.Builder()
.connectTimeout(TIME_OUT, SECONDS)
.readTimeout(TIME_OUT, SECONDS)
.writeTimeout(TIME_OUT, SECONDS)
.addInterceptor(loggingInterceptor)
.addInterceptor(authInterceptor)
// .authenticator(ServiceAuthenticator())
.build()
}
}
}
ServiceModule.kt
@Module
abstract class ServiceModule {
companion object {
@Singleton
@Provides
fun provideTestimonialService(@RetrofitType(BASIC) retrofit: Retrofit): TestimonialRestService {
return retrofit.create(TestimonialRestService::class.java)
}
}
}