Search code examples
androidmobiledependency-injectionkotlinkoin

koin default implementation without name reference


I have 2 Retrofit Clients one of them default and second one has different implementation like (base URL, interceptors etc... )

i need to inject default client without using name reference

first client :-

single<Retrofit> {
Retrofit.Builder()
        .baseUrl(RemoteConstants.BASE_URL)
        .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
        .addConverterFactory(APIResponseConverter())
        .addConverterFactory(GsonConverterFactory.create(get()))
        .client(get())
        .build()
    }

Second Client:-

single<Retrofit>("retrofit_second") {
        Retrofit.Builder()
                .baseUrl("diffrent url")
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create(get()))
                .client(get("SecondOkHttpClient"))
                .build()
}

My way to inject

val myModule = module {
    factory { get<Retrofit>().create(FirstAPI::class.java) } // Why Koin did not figure it without providing its default name !?
    factory { get<Retrofit>("retrofit_second").create(SecondAPI::class.java) }
    factory<IMyRemoteDataSource> { MyRemoteDataSource(get(), get()) }
    factory<IMyRepository> { MyRepository(get()) }
    factory { MyUseCase(get()) }
}

the result is :

        Multiple definitions found for type 'class retrofit2.Retrofit' - Koin can't choose between :
    Single [name='retrofit_second',class='retrofit2.Retrofit']
    Single [name='Retrofit',class='retrofit2.Retrofit']

Why Koin did not get the default Retrofit instance without providing its default name (Retrofit ) !?

factory { get<Retrofit>().create(FirstAPI::class.java) }

Solution

  • You are right @Eslam. Current behavior (as of koin:1.0.2) is when you don't specify the dependency name, it is treated as an empty string. And then the definitions get filtered by class name:

    fun searchByClass(clazz: KClass<*>): List<BeanDefinition<*>> {
        return definitions.filter { clazz in it.classes }
    }
    

    As a result you get both of your definitions, which results in the above mentioned error: Multiple definitions for class ....