Wale
Wale

Reputation: 1806

Multi Binding In Dagger2 with Kotlin

So, I have this issue which I think I understand what's happening but I don't know a way out. Note: I'm pretty new to Dagger 2 ...I'm coming from SpringBoot and it pretty lazy out there, so take it easy on me.

I have a module that provides three methods, the last method depends on the first two methods like below:

@Module
class CoreModule {

    @Provides
    @Named("appName")
    fun appName() : String{
        return "Uburu Store"
    }

    @Provides
    @Named("appVersion")
    fun appVersion() : String {
        return "0.0.1"
    }

    @Provides
    @Named("appInfo")
    fun appInfo(appName: String, appVersion: String) : String {
        return "$appName Version:: $appVersion"
    }
}

I'm getting an error that:

[Dagger/MissingBinding] java.lang.String cannot be provided without an @Inject constructor or an @Provides-annotated method.

My ApplicationComponent class:

@Component(modules = [(CoreModule::class), (AndroidSupportInjectionModule::class), (ActivityBuildersModule::class)])
interface ApplicationComponent : AndroidInjector<ApplicationClass> {

    fun inject(application: Application)

    @Component.Builder
    interface Builder {

        @BindsInstance
        fun application(application: Application?): Builder?

        fun build(): ApplicationComponent?
    }

}

My activity class:

class MainActivity : DaggerAppCompatActivity() {

    @Inject @Named("appInfo") lateinit var appInfo : String

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        Toast.makeText(this, appInfo, Toast.LENGTH_LONG).show()
    }
}

I managed to make it work if I don't use @Named annotation in any of the two dependencies i.e if I delete one of the Two provided dependencies from CoreModule, and remove the @Named annotation from the only dependency left, it will work fine like below:

    @Module
    class CoreModule {
    
        @Provides
        fun appName() : String{
            return "Uburu Store"
        }
    
        @Provides
        @Named("appInfo")
        fun appInfo(appName: String) : String {
            return "$appName Version:: $"
        }
    
    }
//This will work just fine, which made me realize that the @Named must be making it difficult for Dagger to understand something.

The problem with this approach is that I can't do without the @Named as it's needed for Multiple Binding of the same DataTypes e.g: String.

My research so far made it known to me that I have to use @JvmSuppressWildcards somewhere but I'm not sure where.

Upvotes: 0

Views: 444

Answers (1)

Droid
Droid

Reputation: 568

Dagger provides a dependency based on class types in the graph, in your first code snippet of CoreModule it fails to provide dependencies into the appInfo(String, String) method because it cannot figure out which String type belongs where. The fix is simple; annotate the dependencies that you have already provided with the @Named qualifier in the method that requires them within the module:

@Module
class CoreModule {

    @Provides
    @Named("appName")
    fun appName() : String{
        return "Uburu Store"
    }

    @Provides
    @Named("appVersion")
    fun appVersion() : String {
        return "0.0.1"
    }

    @Provides
    @Named("appInfo")
    fun appInfo(@Named("appName") appName: String, @Named("appVersion") appVersion: String) : String {
        return "$appName Version:: $appVersion"
    }
}

Your second example works because there is only one String type to be provided from the graph.

For more information head over to the documentation and scroll to Qualifier section

Upvotes: 2

Related Questions