使用匕首柄作为依赖注入来处理多个改造客户端?

Man*_*mad 21 android retrofit2 dagger-hilt

我想在我的 android 应用程序中使用两个不同的后端,具有不同的响应格式,我使用 hilt 作为依赖注入,并对网络调用进行改造,这非常适合工作。

因为我已经添加了第二个服务器网络文件和应用程序模块,所以它给了我错误,该错误列在最后。

我需要知道在这种情况下的出路,而不需要进行任何显着的架构更改。

@Keep
@Module
@InstallIn(SingletonComponent::class)
object AppModule {
@Singleton
@Provides
fun provideRetrofit(gson: Gson,@ApplicationContext appContext: Context): Retrofit = Retrofit.Builder()
    .client(
        OkHttpClient().newBuilder()
            .addInterceptor(HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY)).readTimeout(80,TimeUnit.SECONDS)
            .addInterceptor(
                ChuckerInterceptor.Builder(appContext)
                    .collector(ChuckerCollector(appContext))
                    .maxContentLength(250000L)
                    .redactHeaders(emptySet())
                    .alwaysReadResponseBody(false)
                    .build()
            )
            .build()
    )
    .baseUrl(UtilSingleton.instance!!.GetBaseUrl())
    .addConverterFactory(GsonConverterFactory.create(gson))
    .build()

@Provides
fun provideGson(): Gson = GsonBuilder().create()

@Provides
fun providePostsService(retrofit: Retrofit): ApiService =
    retrofit.create(ApiService::class.java)

@Singleton
@Provides
fun provideApiRemoteDataSource(apiService: ApiService) = ApiRemoteDataSource(apiService)

@Singleton
@Provides
fun provideRepository(
    remoteDataSource: ApiRemoteDataSource
) =
    MainRepo(remoteDataSource)


/**----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------**/

@Singleton
@Provides
fun provideRetrofitEmall(gson: Gson,@ApplicationContext appContext: Context): Retrofit = Retrofit.Builder()
        .client(
                OkHttpClient().newBuilder()
                        .addInterceptor(HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY)).readTimeout(80,TimeUnit.SECONDS)
                        .addInterceptor(
                                ChuckerInterceptor.Builder(appContext)
                                        .collector(ChuckerCollector(appContext))
                                        .maxContentLength(250000L)
                                        .redactHeaders(emptySet())
                                        .alwaysReadResponseBody(false)
                                        .build()
                        )
                        .build()
        )
        .baseUrl(UtilSingleton.instance!!.GetBaseUrl())
        .addConverterFactory(GsonConverterFactory.create(gson))
        .build()

@Provides
fun providePostsServiceEmall(retrofit: Retrofit): EmallApiService =
        retrofit.create(EmallApiService::class.java)

@Singleton
@Provides
fun provideApiRemoteDataSource(apiService: EmallApiService) = EmallApiRemoteDataSource(apiService)

@Singleton
@Provides
fun provideRepository(
        remoteDataSource: EmallApiRemoteDataSource
) =
        EmallRepo(remoteDataSource)

}
Run Code Online (Sandbox Code Playgroud)

构建错误->

Execution failed for task ':app:kaptLocalDebugKotlin'.
> A failure occurred while executing org.jetbrains.kotlin.gradle.internal.KaptExecution
> java.lang.reflect.InvocationTargetException (no error message)
Run Code Online (Sandbox Code Playgroud)

完整日志 ->

 D:\vaultsNew\vaultspaynewapis\app\build\tmp\kapt3\stubs\localDebug\com\uae\myvaultspay\di\AppModule.java:40: error: Cannot have more than one binding method with the same name in a single module
public final com.uae.myvaultspay.data.remote.ApiRemoteDataSource provideApiRemoteDataSource(@org.jetbrains.annotations.NotNull()
                                                                 ^D:\vaultsNew\vaultspaynewapis\app\build\tmp\kapt3\stubs\localDebug\com\uae\myvaultspay\di\AppModule.java:78: error: Cannot have more than one binding method with the same name in a single module
public final com.uae.myvaultspay.data.remote.emallremote.EmallApiRemoteDataSource provideApiRemoteDataSource(@org.jetbrains.annotations.NotNull()
                                                                                  ^D:\vaultsNew\vaultspaynewapis\app\build\tmp\kapt3\stubs\localDebug\com\uae\myvaultspay\di\AppModule.java:48: error: Cannot have more than one binding method with the same name in a single module
public final com.uae.myvaultspay.data.repository.MainRepo provideRepository(@org.jetbrains.annotations.NotNull()
                                                          ^D:\vaultsNew\vaultspaynewapis\app\build\tmp\kapt3\stubs\localDebug\com\uae\myvaultspay\di\AppModule.java:86: error: Cannot have more than one binding method with the same name in a single module
public final com.uae.myvaultspay.data.repository.EmallRepo provideRepository(@org.jetbrains.annotations.NotNull()
                                                           ^warning: 
File for type 'com.uae.myvaultspay.MyApplication_HiltComponents' created 
in the last round will not be subject to annotation processing.
Execution failed for task ':app:kaptLocalDebugKotlin'.
> A failure occurred while executing 
org.jetbrains.kotlin.gradle.internal.KaptExecution
> java.lang.reflect.InvocationTargetException (no error message)
Run Code Online (Sandbox Code Playgroud)

Dươ*_*inh 45

如果你想使用 Dagger 或 Hilt 返回 Retrofit 客户端,那么你应该使用@Named注释。此注释可帮助 Hilt 或 Dagger 了解您使用相同的 Retrofit 返回类型,即您需要获取哪个 Retrofit 实例。

按照以下方式,您可以提供带有刀柄或匕首的多个改造实例。

首先,我看到你提供了2个改造实例。@Named为您提供的每个改造实例添加注释。

object AppModule {

   @Singleton
   @Provides
   @Named("Normal")
   fun provideRetrofit(gson: Gson, @ApplicationContext appContext: Context): Retrofit = ...

   @Singleton
   @Provides
   @Named("Email")
   fun provideRetrofitEmall(gson: Gson, @ApplicationContext appContext: Context): Retrofit = ...
}
Run Code Online (Sandbox Code Playgroud)

接下来,当您提供api服务时,向Hilt或Dagger指定它需要哪个retrofit实例。

object AppModule {

   @Provides
   fun providePostsService(@Named("Normal") retrofit: Retrofit): ApiService = retrofit.create(ApiService::class.java)

   @Provides
   fun providePostsServiceEmall(@Named("Email") retrofit: Retrofit): EmallApiService = retrofit.create(EmallApiService::class.java)
}
Run Code Online (Sandbox Code Playgroud)

最后,清理项目并重建项目以查看结果。


Ami*_*aza 14

科特林语言

您可以通过使用来实现Qualifier。让我们看一个例子:

  1. 创建一个 kotlin 类,例如 Qualifiers.kt 并定义Qualifier您需要的

    import javax.inject.Qualifier
    
    @Qualifier
    @Retention(AnnotationRetention.BINARY)
    annotation class Auth
    
    @Qualifier
    @Retention(AnnotationRetention.BINARY)
    annotation class Setting
    
    Run Code Online (Sandbox Code Playgroud)
  2. 您的模块类,例如 NetworkModule.kt

    @Provides
    @Singleton
    @Auth   //This will differentiate retrofit object
    fun retrofitAuth(
       client: OkHttpClient,
       gsonConverterFactory: GsonConverterFactory
    ): Retrofit =
         Retrofit.Builder()
             .client(client)
             .addConverterFactory(gsonConverterFactory)
             .baseUrl("https://someauth.baseurl.com").build()
    
    
    @Provides
    @Singleton
    @Setting   //This will differentiate retrofit object
    fun retrofitSetting(
       client: OkHttpClient,
       gsonConverterFactory: GsonConverterFactory
    ): Retrofit =
         Retrofit.Builder()
             .client(client)
             .addConverterFactory(gsonConverterFactory)
             .baseUrl("https://someSetting.baseurl.com").build()
    
    
     //Build Api services with respect to qualifiers
    
     @Provides
     @Singleton
     fun authApiService(@Auth retrofit: Retrofit): AuthApiService = retrofit.create(AuthApiService::class.java)
    
    
     @Provides
     @Singleton
     fun settingApiService(@Setting retrofit: Retrofit): SettingApiService = retrofit.create(SettingApiService::class.java)
    
    Run Code Online (Sandbox Code Playgroud)
  3. 您的Api服务类,例如AuthApiService和SettingApiService

     interface AuthApiService {
    
          @FormUrlEncoded
          @POST("login/v2")
          fun login(@FieldMap params: HashMap<String, Any>): Response<LoginResponse>
     }
    
    
     interface SettingApiService {
    
          @GET("settings")
          fun settings(): Response<SettingsResponse>
    
          @GET("faqs")
          fun getFAQs(): Response<FAQsResponse>
    
     }
    
    Run Code Online (Sandbox Code Playgroud)

PS:在某些情况下你还需要不同的okhttp客户端。Qualifier在这种情况下,也可以通过不同的Okhttp客户端来实现。