Home > Net >  Why it doesn't have @Inject for dependency injection?
Why it doesn't have @Inject for dependency injection?

Time:04-27

I am reading some code and have trouble understanding

import dagger.Component
import dagger.Module
import dagger.Provides
import javax.inject.Inject


class Sound(val noise: String)

class Dog @Inject constructor(val sound: Sound)

@Module
class DogModule() {
    @Provides
    fun provideWoWo(): Sound = Sound("wowo")

    @Provides
    fun provideDog(sound : Sound): Dog = Dog(sound)
}

@Component(modules = [ DogModule::class ])
interface AnimalComponent {
    val dog: Dog
}

fun main() {
    val component = DaggerAnimalComponent.create()
    println("The dog has sound ${component.dog.sound.noise}.")
}

why class Sound(val noise: String) without @Inject?

I thought it would be class Sound @Inject constructor(val noise: String)

since Sound class instance is also created via dagger just like Dog class instance

CodePudding user response:

Because you explicitly set the @Provides with constructor parameter. @Inject is used to omit the @Provides. In your code the @Inject on Dog can be removed as well.

To sum up - you don't have to add @Inject if you are creating this class with @Provides

CodePudding user response:

since Sound class instance is also created via dagger just like Dog class instance

This isn't correct: Neither Dog nor Sound is being created via Dagger. Dagger allows Dog and Sound to be injected, but in the Module you are creating the instances in the @Provides methods/functions you define.

This also means that @Inject annotations for both Dog and Sound are currently ignored, because Dagger is not a part of the construction of those objects. Instead, you are providing those yourself: @Provides methods and functions can receive objects in the graph, which Dagger will provide, and that's how you are receiving Sound as part of the @Provides Dog method. As a consequence, if Dog's constructor argument list were ever to change, you would need to change the @Provides method yourself. Dagger also won't automatically populate @Inject-annotated methods and fields, labeled in the docs as "method injection" and "field injection".

If you were to delete the @Provides method for Dog, then Dagger would read the argument list itself and react automatically when it changes. Method and field injection would also work automatically then.

As a consequence, you never need to use @Provides on a class with an @Inject constructor unless you want to override or customize the arguments passed into the constructor. I recommend using @Inject wherever possible and reserving @Provides only for code you don't control or for other special cases. See my other SO answer here: Android Dagger 2: Inject versus Provides

  • Related