Inject two objects of the same class with different fields using named in Dagger2

Issue

Suppose I have rectangle class implementing shape interface

class Rectangle @Inject constructor(private val id: String) : Shape {
    override fun info() {
        Log.d("Rectangle", "I am rectangle!, My id is $id")
    }
}



interface Shape {
    fun info()
}

One way of providing two objects of the same class with different id using @Named would be inside my module:

@Module
class AppModule {

    @Provides
    @Named("Id1")
    fun provideId1(): Shape {
        return Rectangle("Id1")
    }

    @Provides
    @Named("Id2")
    fun provideId2(): Shape {
        return Rectangle("Id2")
    }
}

With that I can inject two rectangle objects in my mainactivity

    @Inject
    @field:Named("Id1")
    lateinit var rect1: Shape

    @Inject
    @field:Named("Id2")
    lateinit var rect2: Shape

However I would like my Module to look little bit different. Inside it I want to provide shape and using @named constructor parameters for objects. What I have is:

  @Module
class AppModule {

    @Provides
    @Named("Id1")
    fun provideId1(@Named("id1") id: String): Shape {
        return Rectangle(id)
    }

    @Provides
    @Named("Id2")
    fun provideId2(@Named("id2") id: String): Shape {
        return Rectangle(id)
    }

    @Provides
    @Named("id1")
    fun provideId1(): String {
        return "ABC"
    }

    @Provides
    @Named("id2")
    fun provideId2(): String {
        return "XYZ"
    }
}

How can I achieve injection of two objects with different constructor parameters using such approach?

Solution

As per my comment,

Aha, i got it. I think. They can’t be in the same module. The reason is: while the module is being processed, it will provide named strings, but they will not be in the graph to meet the criteria for providing the rectangle-providing methods with those named parameters. You will need to move string-providing methods to a different module, and make your AppModule use it as a dependency. Then it should work. However, this is just a best-effort guess

try something like this instead:

@Module(include  StringProvidingModule::class)
class AppModule {

    @Provides
    @Named("Id1")
    fun provideId1(@Named("id1") id: String): Shape {
        return Rectangle(id)
    }

    @Provides
    @Named("Id2")
    fun provideId2(@Named("id2") id: String): Shape {
        return Rectangle(id)
    }
}

@Module
class StringProvidingModule {

    @Provides
    @Named("id1")
    fun provideId1(): String {
        return "ABC"
    }

    @Provides
    @Named("id2")
    fun provideId2(): String {
        return "XYZ"
    }
}

Answered By – Shark

Leave a Comment