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