Reputation: 449
I am trying to implement multiple instance of retrofit for two different base URL`s using Dagger2 and MVVM. I have already wasted a huge amount of time testing different approaches provided here in SO, but still unable to figure it out. I have created new Qualifiers as well and created a new instance but all my request are still made using first instance.Here is my implementation.
Qualifiers
@Retention(AnnotationRetention.BINARY)
@Qualifier
annotation class APIService1
@Retention(AnnotationRetention.BINARY)
@Qualifier
annotation class APIService2
AppModule class
@AssistedModule
@Suppress("unused")
@Module(includes = [ViewModelModule::class, CoreDataModule::class, AssistedViewModelModule::class, AssistedInject_AppModule::class])
class AppModule {
@Singleton
@Provides
fun provideServices(
APIService1 okHttpClient: OkHttpClient, converterFactory: MoshiConverterFactory
) =
provideService(okHttpClient, converterFactory, MyApi::class.java)
@Singleton
@Provides
@APIService2
fun provideMicroServices(
APIService1 okHttpClient: OkHttpClient, converterFactory: MoshiConverterFactory
) =
provideMicroService(okHttpClient, converterFactory, MyApi::class.java)
@APIService1
@Provides
fun providePrivateOkHttpClient(upstreamClient: OkHttpClient): OkHttpClient {
return upstreamClient.newBuilder().build()
}
@Singleton
@Provides
fun provideRemoteDataSource(myApiService: MyApi) = RemoteDataSource(myApiService)
private fun createRetrofit(
okhttpClient: OkHttpClient,
converterFactory: MoshiConverterFactory
): Retrofit {
Retrofit.Builder()
.baseUrl("https://example1.com/api/")
.client(okhttpClient)
.addConverterFactory(converterFactory)
.build()
}
private fun createMicroServiceRetrofit(
okhttpClient: OkHttpClient,
converterFactory: MoshiConverterFactory
): Retrofit {
Retrofit.Builder()
.baseUrl("https://example2.com/api/")
.client(okhttpClient)
.addConverterFactory(converterFactory)
.build()
}
private fun <T> provideService(
okhttpClient: OkHttpClient,
converterFactory: MoshiConverterFactory, clazz: Class<T>
): T {
return createRetrofit(okhttpClient, converterFactory).create(clazz)
}
private fun <T> provideMicroService(
okhttpClient: OkHttpClient,
converterFactory: MoshiConverterFactory, clazz: Class<T>
): T {
return createMicroServiceRetrofit(okhttpClient, converterFactory).create(clazz)
}
}
CoreDataModule class
@Module
class CoreDataModule {
@Provides
fun provideOkHttpClient(): OkHttpClient {
val interceptor = HttpLoggingInterceptor()
interceptor.level = HttpLoggingInterceptor.Level.BODY
val client = OkHttpClient().newBuilder()
.connectTimeout(15, TimeUnit.SECONDS)
.readTimeout(90, TimeUnit.SECONDS)
.writeTimeout(60, TimeUnit.SECONDS)
.retryOnConnectionFailure(false)
return client.build()
}
@Provides
@Singleton
fun provideMoshi(): Moshi = Moshi.Builder().build()
@Provides
@Singleton
fun provideMoshiConverterFactory(): MoshiConverterFactory =
MoshiConverterFactory.create()
}
RemoteDataSource Class
@Keep
class RemoteDataSource @Inject constructor(private val service: MyApi) : BaseDataSource() {
suspend fun getOtp(data: String) = getResult { service.getOtp(data) }
suspend fun getData(data: String) = getResult { service.getData(data) }
}
BaseDataSource Class
abstract class BaseDataSource {
protected suspend fun <T> getResult(call: suspend () -> Response<T>): Result<T> {
val response = call()
if (response.isSuccessful) {
val body = response.body()
if (body != null) return Result.success(body)
}
return error(" ${response.code()} ${response.message()}")
}
}
MyApi Class
interface MyApi {
@POST("Register/Otp")
@FormUrlEncoded
suspend fun getOtp(@Field("data") data: String): Response<OtpResponse>
@POST("Home/Data")
@FormUrlEncoded
suspend fun getData(@Field("data") data: String): Response<DataResponse>
}
This is how i am using it in my ViewModel
One of My ViewModles
class OtpViewModel @Inject constructor(
private val remoteDataSource: RemoteDataSource
) :
ViewModel() {
fun getNewOtp() = liveData {
try {
emit(Resource.loading(data = null))
val response = remoteDataSource.getOtp(params))
emit(Resource.success(data = response))
} catch (e: Exception) {
emit(Resource.error(data = null, message = e.message ?: e.localizedMessage.orEmpty()))
}
}
Upvotes: 1
Views: 2309
Reputation: 44861
Create 2 annotations like this:
@Qualifier
@Target(
AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER,
AnnotationTarget.PROPERTY_SETTER, AnnotationTarget.FIELD,
AnnotationTarget.VALUE_PARAMETER
)
@Retention(AnnotationRetention.BINARY)
annotation class ApiService1
@Qualifier
@Target(
AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER,
AnnotationTarget.PROPERTY_SETTER, AnnotationTarget.FIELD,
AnnotationTarget.VALUE_PARAMETER
)
@Retention(AnnotationRetention.BINARY)
annotation class ApiService2
Change your providers with:
@Provides
@Singleton
@ApiService1
fun provideServices(....): MyApi {
return ...
}
@Provides
@Singleton
@ApiService2
fun provideMicroServices(....): MyApi {
return ...
}
Then in your Android classes you can do this:
class MyActivity : FragmentActivity() {
@Inject
@ApiService1
lateinit var retrofit1: MyApi
@Inject
@ApiService2
lateinit var retrofit2: MyApi
....
}
Or in classes:
class Repository @Inject constructor (
@ApiService1 retrofit1: MyApi
) {
....
}
Upvotes: 3