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
