使用 dagger2 和 MVVM 为两个不同的基础 URL`s 创建多个改造实例
Create multiple retrofit instances for two different base URL`s using dagger2 and MVVM
我正在尝试使用 Dagger2 和 MVVM 为两个不同的基础 URL 实现多个改造实例。我已经浪费了大量时间来测试 SO 中提供的不同方法,但仍然无法弄清楚。我也创建了新的限定符并创建了一个新实例,但我的所有请求仍然首先使用 instance.Here 是我的实现。
预选赛
@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)
}
}
核心数据模块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>
}
这就是我在 ViewModel 中使用它的方式
我的一个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()))
}
}
像这样创建 2 个注释:
@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
更改您的提供商:
@Provides
@Singleton
@ApiService1
fun provideServices(....): MyApi {
return ...
}
@Provides
@Singleton
@ApiService2
fun provideMicroServices(....): MyApi {
return ...
}
然后在你的 Android 类 你可以这样做:
class MyActivity : FragmentActivity() {
@Inject
@ApiService1
lateinit var retrofit1: MyApi
@Inject
@ApiService2
lateinit var retrofit2: MyApi
....
}
或在类中:
class Repository @Inject constructor (
@ApiService1 retrofit1: MyApi
) {
....
}
我正在尝试使用 Dagger2 和 MVVM 为两个不同的基础 URL 实现多个改造实例。我已经浪费了大量时间来测试 SO 中提供的不同方法,但仍然无法弄清楚。我也创建了新的限定符并创建了一个新实例,但我的所有请求仍然首先使用 instance.Here 是我的实现。
预选赛
@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)
}
}
核心数据模块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>
}
这就是我在 ViewModel 中使用它的方式
我的一个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()))
}
}
像这样创建 2 个注释:
@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
更改您的提供商:
@Provides
@Singleton
@ApiService1
fun provideServices(....): MyApi {
return ...
}
@Provides
@Singleton
@ApiService2
fun provideMicroServices(....): MyApi {
return ...
}
然后在你的 Android 类 你可以这样做:
class MyActivity : FragmentActivity() {
@Inject
@ApiService1
lateinit var retrofit1: MyApi
@Inject
@ApiService2
lateinit var retrofit2: MyApi
....
}
或在类中:
class Repository @Inject constructor (
@ApiService1 retrofit1: MyApi
) {
....
}