0

I am new to Dagger 2 and I am trying to learn it with Kotlin. Let me explain my Project structure first. I am having a Class name "Info":

class Info constructor(var message: String) {}

I have created a module for this class "InfoModule"

    @Module
    class InfoModule {

        @Provides @Choose("HELLO")
        fun sayHello(): Info{
            return Info(message = "Hello dagger 2")
        }

        @Provides @Choose("HI")
        fun sayHi(): Info{
            return Info(message = "Hi dagger 2")
        }
}

I have created a component interface for this module named "MagicBox"

  @Component(modules = [InfoModule::class])
interface MagicBox {
    fun poke(app: MainActivity)
}

Then in the MainActivity I have injected the two fields for "Info"

 class MainActivity : AppCompatActivity() {



    var textView: TextView? = null;

    @Inject @field:Choose("HELLO") lateinit var infoHello: Info
    @Inject @field:Choose("HI") lateinit var infoHi: Info


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


        DaggerMagicBox.create().poke(this)

        textView = findViewById<TextView>(R.id.textView)
        textView!!.text = infoHi.message

    }
}

@Qualifier
@MustBeDocumented
@kotlin.annotation.Retention(AnnotationRetention.RUNTIME)
annotation class Choose(val value: String)

As you see above I haved created a @Choose annotation to learn how @Qualifier works. Up to here the code works perfectly and it is really a magic of Dagger :).

PROBLEM STARTS HERE:>> Then I decided to Inject another field called "car" inside my MainActivity in the same way the "info" field is injected in the MainActivity. To do that first i need a Car class.

    class Car constructor(var engine: Engine, var wheels: Wheels) {

fun drive(){
    Log.d("Car","Driving")
}
}

Now the car class needs Engine and Wheels. So below are Engine and Wheel classes

Engine Class:

class Engine  {
}

Wheel Class:

    class Wheels  {
}

Then I have created a Module for Car class

 @Module
class CarModule {

@Provides
fun provideEngine(): Engine{
   return Engine()
}

@Provides
fun provideWheel(): Wheels{
    return Wheels()
}

@Provides @Choose("NewCar")
fun provideCar(engine: Engine, wheels: Wheels): Car{
    Log.d("NewCar", "Created")
    return Car(engine, wheels)
}

}

The component for Car is below

 @Component (modules = [CarModule::class])
interface CarComponent {

    fun injectCar(mainActivity: MainActivity)


}

Then I have injected the car field in the MainActivity and I have tried to called the "drive" method of Car class. Now my MainActivity looks like this.

    class MainActivity : AppCompatActivity() {



    var textView: TextView? = null;


    @Inject @field:Choose("HELLO") lateinit var infoHello: Info
    @Inject @field:Choose("HI") lateinit var infoHi: Info

    @Inject @field:Choose("NewCar") lateinit var  car: Car

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


        DaggerMagicBox.create().poke(this)
        textView = findViewById<TextView>(R.id.textView)
        textView!!.text = infoHi.message


        DaggerCarComponent.create().injectCar(this)
        car.drive()


    }
}

@Qualifier
@MustBeDocumented
@kotlin.annotation.Retention(AnnotationRetention.RUNTIME)
annotation class Choose(val value: String)

The Logcat Error after MakeProject:

    error: [Dagger/MissingBinding] @de.test.testtheapp.Choose("HELLO") de.test.testtheapp.Api.Info cannot be provided without an @Provides-annotated method.
public abstract interface CarComponent {
                ^
      @de.test.testtheapp.Choose("HELLO") de.test.testtheapp.Api.Info is injected at
          de.test.testtheapp.MainActivity.infoHello
      de.test.testtheapp.MainActivity is injected at
          de.test.testtheapp.Components.CarComponent.injectCar(de.test.testtheapp.MainActivity)

What i really find strange is that although the "info" field injection was working prefectly before, why after adding car field injection, the logcat is now showing error about info field injection or Info class. I know its also saying something about "CarComponent". Now nothing is working. Even the "DaggerMagicBox" is unresolved. I am clueless about the error and I am stuck on this since two days. My knowledge about dagger is very limited that I don't know what is the solution. I will be very thankful if some give me a clue. I am using Android Studio 3.5.1 and Dagger version 2.21

2
  • you use infoHi.message before inject that DaggerMagicBox.create().poke(this) Commented Oct 10, 2019 at 8:35
  • @RofieSagara No, sorry that was a mistake i made while copying my code in the stackoverflow question above. Actually i used info.Hi after DaggerMagicBox.create().poke(this). I corrected it above. Commented Oct 10, 2019 at 8:40

1 Answer 1

1

You are trying to use CarComponent to inject dependencies of MainActivity:

DaggerCarComponent.create().injectCar(this)

But your CarComponent doesn't have a way to provide Info:

@Inject @field:Choose("HELLO") lateinit var infoHello: Info

Because the provider method is defined in InfoModule and CarComponent doesn't have it in its modules list.


You are using two components to inject the dependencies of MainActivity:

DaggerMagicBox.create().poke(this)
...
DaggerCarComponent.create().injectCar(this)

You should only use one.

Either add the CarModule to the list of modules of MagicBox and remove DaggerCarComponent.create().injectCar(this).

Or add the InfoModule to the list of modules of CarComponent and remove DaggerMagicBox.create().poke(this)

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.