使用 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
) {
  ....
}