developKinberg
developKinberg

Reputation: 383

Android Hilt use two Retrofit2 clients

I want to setup two Retrofit2 clients with Dagger Hilt, because my application fetch informations from two different api's. But when I run my code the following exception is thrown ->

App_HiltComponents.java:128: error: [Dagger/DuplicateBindings] retrofit2.Retrofit is bound multiple times:
      public abstract static class SingletonC implements HiltWrapper_ActivityRetainedComponentManager_ActivityRetainedComponentBuilderEntryPoint,
                             ^
          @org.jetbrains.annotations.NotNull @Provides retrofit2.Retrofit de.kotlinbooks.di.NetworkBooksModule.retrofitBooks(okhttp3.OkHttpClient)
          @org.jetbrains.annotations.NotNull @Provides retrofit2.Retrofit de.kotlinbooks.di.NetworkNYTModule.retrofitNYT(okhttp3.OkHttpClient)

I know that the retrofit client is a singleton, so I split my modules in two files for the different api's. This is my code ->

NetworkBooksModule

@Module
@InstallIn(SingletonComponent::class)
class NetworkBooksModule {

    @Provides
    fun okHttpClient(): OkHttpClient {
        val levelType: HttpLoggingInterceptor.Level = if (BuildConfig.DEBUG)
            HttpLoggingInterceptor.Level.BODY else HttpLoggingInterceptor.Level.NONE

        val logging = HttpLoggingInterceptor()
        logging.setLevel(levelType)

        return OkHttpClient.Builder()
            .addInterceptor(logging)
            .build()
    }

    @Provides
    fun retrofitBooks(okHttpClient: OkHttpClient): Retrofit {
        return Retrofit.Builder()
            .baseUrl("https://www.googleapis.com/books/v1/")
            .client(okHttpClient)
            .addConverterFactory(MoshiConverterFactory.create())
            .build()
    }

    @Provides
    fun bookService(retrofit: Retrofit): BookService {
        return retrofit.create(BookService::class.java)
    }

    @Provides
    fun bookClient(bookService: BookService): BookClient {
        return BookClient(bookService)
    }
}

NetworkNYTModule

@Module
@InstallIn(SingletonComponent::class)
class NetworkNYTModule {

    @Provides
    fun okHttpClient(): OkHttpClient {
        val levelType: HttpLoggingInterceptor.Level = if (BuildConfig.DEBUG)
            HttpLoggingInterceptor.Level.BODY else HttpLoggingInterceptor.Level.NONE

        val logging = HttpLoggingInterceptor()
        logging.setLevel(levelType)

        return OkHttpClient.Builder()
            .addInterceptor(logging)
            .build()
    }

    @Provides
    fun retrofitNYT(okHttpClient: OkHttpClient): Retrofit {
        return Retrofit.Builder()
            .baseUrl("https://api.nytimes.com/svc/books/v3/")
            .client(okHttpClient)
            .addConverterFactory(MoshiConverterFactory.create())
            .build()
    }

    @Provides
    fun nytService(retrofit: Retrofit): NYTService {
        return retrofit.create(NYTService::class.java)
    }

    @Provides
    fun nytClient(nytService: NYTService): NYTClient {
        return NYTClient(nytService)
    }
}

Upvotes: 3

Views: 2934

Answers (3)

@Provides
@Named("booksRetrofit")
    fun retrofitBooks(okHttpClient: OkHttpClient): Retrofit {
        return Retrofit.Builder()
            .baseUrl("https://www.googleapis.com/books/v1/")
            .client(okHttpClient)
            .addConverterFactory(MoshiConverterFactory.create())
            .build()
    }

    @Provides
    fun bookService(@Named("booksRetrofit") retrofit: Retrofit): BookService {
        return retrofit.create(BookService::class.java)
    }

@Provides
@Named("nytRetrofit")
    fun retrofitNYT(okHttpClient: OkHttpClient): Retrofit {
        return Retrofit.Builder()
            .baseUrl("https://api.nytimes.com/svc/books/v3/")
            .client(okHttpClient)
            .addConverterFactory(MoshiConverterFactory.create())
            .build()
    }

    @Provides
    fun nytService(@Named("nytRetrofit") retrofit: Retrofit): NYTService {
        return retrofit.create(NYTService::class.java)
    }

Upvotes: 0

Rustam Sobitov
Rustam Sobitov

Reputation: 1

private fun setUrl(url: String){
    val field: Field = Retrofit::class.java.getDeclaredField("baseUrl")
    field.isAccessible = true
    val newHttpUrl = url.toHttpUrlOrNull()
    field.set(retrofit, newHttpUrl)
}

Upvotes: 0

Saeid Lotfi
Saeid Lotfi

Reputation: 2137

You can use the interface to provide your retrofit instead of Retrofit itself

@Module
@InstallIn(SingletonComponent::class)
class NetworModule {

    @Provides
    fun retrofitNYT(okHttpClient: OkHttpClient): NYTService{
        return Retrofit.Builder()
            .baseUrl("https://api.nytimes.com/svc/books/v3/")
            .client(okHttpClient)
            .addConverterFactory(MoshiConverterFactory.create())
            .build()
            .create(NYTService::class.java)
    }

    @Provides
    fun retrofitBooks(okHttpClient: OkHttpClient): BookService{
        return Retrofit.Builder()
            .baseUrl("https://www.googleapis.com/books/v1/")
            .client(okHttpClient)
            .addConverterFactory(MoshiConverterFactory.create())
            .build()
            .create(BookService::class.java)
    }

}

Upvotes: 6

Related Questions