简体   繁体   中英

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 ie 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 eg: String.

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM