Dagger is a fully static, compile-time dependency injection framework for Java, Kotlin, and Android It is created by Square and now maintained by Google. we use it to automate DI for our application
if class is depend on anther class like Class A is depend on Class B that mean class A has
reference of Class B like this image Injection simply means passing dependency from outside class
the idea
- Reduce boilerplate code
- Decoupled build dependencies
- improving testing | Classify Dependency |:---------------------------:| :
|

class Care(val engine: Engine, val wheels: Wheels) {
fun drive() {
}
} fun main() {
val blocks = Block()
val cylinder = Cylinder()
val engine = Engine(blocks, cylinder)
val wheals = Whelas(Tires(), Rimes())
val car = car(engine, wheals)
} fun main() {
val carComponet = DaggerCarComponent.create()
val car = carComponet.getCar()
}Class car depend on two class engine and wheels let is start how dagger work to provide automated dependency
Dependancy provide using annotation @Inject you can add it for classes can edit on them or another
way using @Module and you can provide object using @Provides
Creator that responsible for create DAG Dependency Ayclic Graph using annotation @Component
- First create CareComponent as interface this is backbone initialize DAG
kotlin @Component interface CareComponent { fun getCar():Care }
- Using injection annotation
@injectif you can inject Constructor for your classes that mean we can edit at this classes for exampleCar,Engine - Using class module and annotation
@Moduleabove class and add this class to modules for component to know another way provide object checkWhealsModuleand using@providestop the method provide object
@Module
class WhealsModule {
@Provides
fun provideRimes(): Rimes = Rimes()
}- We can use
@BindswithModulethat provide instance for abstraction class for examplePetrolEngineImplementEngineInterface andCarclass depend on Engine to provide it create as likePetrolEngineModule
@Module
abstract class PetrolEngineModule {
@Binds
abstract fun bindPetrolEngine(petrolEngine: PetrolEngine): Engine
}- We can use
@Namedif provide same type object different way and want to determine which one can used at injection if used many at our project then we can create modifier to avoid mistake write name Correctly using Qualifier like@Capicty,@HorsePower - we can inject value of object at run time that check file
DiesleEngineModule - We can using
@Singletonin case of want one object used inside apps - We cane use
@Component.Builderanother way bind value at runtime create your specific builder for daggerComponent we will create interface inside
@Component.Builder
interface Builder {
@BindsInstance
fun bindHorseBower(@HorsePower horsePower: Int): Builder// this value bind any int if object need inject ant value
@BindsInstance
fun bindCapacity(@Capacity capacity: Int): Builder
fun getComponent(): CareComponent
}If one dependency at component different scope like Driver class want to one object per application and one care creation per ActivityScope
so we create AppCoponent and object will be the scope like Driver take scope Singleton
@Singleton
@Component
interface AppComponent {
fun getDriver(): Driver
}the create scope for activity called ActivityScope add it to ActivityComponent and it to provide scope activity like Car
@ActivityScope
@Component(
dependencies = [AppComponent::class],
modules = [WhealsModule::class, PetrolEngineModule::class]
)
interface ActivityComponent {
fun getCar(): Care
fun inject(mainActivity: MainActivity)
@Component.Builder
interface Builder {
@BindsInstance
fun bindHorseBower(@HorsePower horsePower: Int): Builder// this value bind any int if object need inject ant value
@BindsInstance
fun bindCapacity(@Capacity capacity: Int): Builder
fun appComponent(appComponent: AppComponent): Builder
fun build(): ActivityComponent
}
}according above code you see activity component used dependencies Appcomponent to provide object for app scope
there is another solution you can use annotation @SubComponnet this solution solve problem if another object want to be scope application
component that easy add @Singleton annotation at provide object but you must be add it AppComponent like getDriver() method
Let you want DiselEngine singleton scope app if we not use subcomponent you need add @Singleton for provide method
and new method AppComponent
@Singleton
@Component(modules = [DieselEngineModule::class])
interface AppComponent {
fun getDriver(): Driver
fun getDieselEngine(): Engine
@Component.Builder
interface Builder {
@BindsInstance
fun bindHorseBower(@HorsePower horsePower: Int): Builder// this value bind any int if object need inject ant value
fun binDieaselModule(dieselEngineModule: DieselEngineModule):Builder
fun build():AppComponent
}
}Look above code we find add method getDieselEngine method and modules provide DieselEngineModule to app component add new builder
because need provide bind instance for horse power so DieselEngine need it to provide Object
If you want new object at the scope of AppComponent must be add method like
fun getDriver(): Driver
fun getDieselEngine(): EngineThis problem and Dagger find solution Use subComponent for ActivityComponent so AppComponent like This
@Singleton
@Component(modules = [DieselEngineModule::class])
interface AppComponent {
fun getActivityComponent(): ActivityComponent // get only for subComponent that depend on AppComponent
@Component.Builder
interface Builder {
@BindsInstance
fun bindHorseBower(@HorsePower horsePower: Int): Builder// this value bind any int if object need inject ant value
@BindsInstance
fun bindCapacity(@Capacity capacity: Int): Builder// this value bind any int if object need inject ant value
fun binDieaselModule(dieselEngineModule: DieselEngineModule): Builder
fun build(): AppComponent
}
}As above code ParentComponent AppComponent that provide Instance child component ActivityComponent just provide one method
of get child component ActivityComponent and this component is subComponent
