Dagger Dagger Before After — Dagger2 with Java Example

Laurence Liu
5 min readOct 21, 2020

The first reaction I met Dagger a few years ago.

The learning curve for Dependency Injection with Dagger is too steep for those without experience with Dependency Injection. So, I spent some time to understand what is DI and realize that I had already used it everywhere in my project. Except I didn’t know that called DI.

After I checked several examples and ran them on my IDE. I found the best one for the practice is the CoffeeApp example from Google. There is also a slide and dev guide talk about the annotations. So, I will just introduce each annotation in brief, and reproduce the code of CoffeShop before knowing Dagger. I hope it could make it easier to understand.

Note: The example from Google already followed the Dependency Inversion Principle. Here are the wiki page for S.O.L.I.D and Dependency Inversion Principle.

Picture from this slide https://tinyurl.com/y22qbw4r.

According to the picture above and the source code.
The CoffeeMaker depends on ElectricHeater and Thermosiphon.
The Thermosiphon depends on ElectricHeater.
All of the CoffeMaker, Thermosiphon, and ElectricHeater are depend on CoffeeLogger.

It’s good to start with the CoffeeLogger. Due to everyone is depending on it.

Import Dagger

Gradle

The latest release version can be found here.

// Add Dagger dependencies
dependencies {
api 'com.google.dagger:dagger:2.x'
annotationProcessor 'com.google.dagger:dagger-compiler:2.x'
}

CoffeeLogger

Here are two annotations that need to pay attention to is this block.

  • @Inject — Let Dagger know how to create instances of this object. There are two steps for @Inject. The first is annotating the new instance of the target. The second is annotating the constructor which depends on the target.
    In this case, the code created a new instance of CoffeeLogger().
  • @Singleton — A kind of @Scope. It provides the dependencies as a singleton as long as it been used the same component. More information from their documentation. (More related articles about @Scope and @Singleton are put in the TL;DR part)

As the dev guild mentioned. @Inject doesn’t work everywhere:

  1. Interfaces can’t be constructed.
  2. Third-party classes can’t be annotated.
  3. Configurable objects must be configured!

And that’s the reason why the other annotations @Module, @Provides, and @Binds come to help.

ElectricHeater

  • @Inject — As the previous block mentioned. The @Inject here is annotating the constructor which depends on the target.
  • @Module — In short, it provides dependency. The generated code followed the Factory Pattern. The methods inside the generated code provide the instance of the target class.
  • @Binds — Same as @Provides. In brief, the most difference between these two is the methods in @Binds don’t have to implement. This makes interface and abstract class is available for @Binds. (More detail in the TL;DR part)

Thermosiphon

This is basically the same stuff as ElectricHeater.

CoffeeMaker

As long as knowing the @Inject annotation, the code after importing dagger becomes more readable and understandable. The reason why I wrote the getCoffeeLogger method in the code before importing dagger is that the CoffeeShop class will need that.

CoffeeShop

  • @Module — This annotation just like an agent or a bridge between @Inject and @Module. It will generate an implementation of that contract. Also known as building the DAG(Directed Acyclic Graph).

CoffeeApp

As the code shows, DaggerCoffeeApp_CoffeeShop is the generated code from Dagger. It followed the Builder Pattern. In this case, CoffeeShop can get the CoffeeMaker and CoffeeLogger without a bunch of redundant code.

The picture above shows the solutions and issues about importing Dagger2. Dagger2 is just like Retrofit. Square and Google make the rules, developers follow the rule. The code becomes cleaner and more readable. Everyone is happy.

For the next section, I will give some examples of an Android project with Dagger2 to see how it rocks the developer's life.

Dagger Dagger Before After — Introduction to Dependency Injection

Dagger Dagger Before After — Dagger2 with Java Example

TL;DR

@Scope and @Singleton

Here are the Stackoverflow and an article talking about the @Scope and @Singleton annotations.

Here is the generated code of DaggerCoffeeApp_CoffeeShop from Dagger with/without the @Singeton annotation.

The code with @Singleton Annotation in CoffeeLogger
The code without @Singleton Annotation in CoffeeLogger

As we can see, the generated code new a CoffeeLogger() every time when the code without @Singleton annotation.

And here is the logs I printed for tract the memory address with/without the @Singeton annotation.

The memory address of the code with @Singleton annotation in CoffeeLogger
The memory address of the code without @Singleton annotation in CoffeeLogger

@Binds and @Provides

The dev-guild from Google gives a great explanation about why and when to use @Binds and @Provides.

--

--