About Dagger 2

Dagger 2 is a fork of Dagger, the dependency injection library created by Square, by Google. The main difference between Dagger 2 compared to Dagger and the other dependency injection libraries is that it works with generated code rather than reflection. Its guiding principle is that the generated code could have been written by a developer, which makes the dependency injection simpler and more efficient. For more information on Dagger 2 design I invite you to watch this presentation by Gregory Kick.

Inside Dagger 2

Modules

Modules are in charge of the creation and the configuration of the dependency to inject thanks to a set of functions annotated by @Provides. Modules are classes annotated by @Module.

Module example:

Exemple de module

Java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

@Module

publicclassApplicationModule{

privateMyApp mApplication;

publicApplicationModule(MyApp application){

this.mApplication=application;

}

@Provides

@Singleton

publicContext provideApplicationContext(){

returnthis.mApplication;

}

@Provides

@Singleton

publicContext provideBus(){

returnnewBus();

}

}

What do we do in this code?

@Module tells that the class is a Dagger 2 module

@Provides tells that the method is a provider for the injection. The name of the method doesn’t matter but the convention wants that it start with “provide”

@Singleton tells that we want to use the same reference every time. In this particular case we didn’t need this annotation because we don’t create a new instance. However it allows the developer to understand what the provider does.

Components

Components are used to group and build modules in an object used to obtain dependencies and/or inject fields. It’s an interface annotated by@Component which implementation will be generated by Dagger 2 during the build. A component must list its composing and depending modules.

The interface can have two kinds of method:

return an object and has no parameters: we return an instance created by Dagger 2 and its dependency are resolved by injection in the constructor

return void but has a parameter: allow to resolve the dependency injection in a non-private field. It’s useful in Android because we don’t create some instance (for example Activity)

Exemple de composant

Java

1

2

3

4

5

6

7

8

@Singleton

@Component(modules=ApplicationModule.class)

publicinterfaceApplicationComponent{

voidinject(BaseActivity baseActivity);

Context context();

Bus bus();

}

What do we do in this code?

@Singleton tells that we want one reference to the component in the application.

If we don’t expose Context and Bus we won’t be able to use them outside our component and we’ll have a build error.

Injection

There are 3 ways to inject dependencies:

Directly calling the dependency on the component

By annotating a property by @Inject and by calling component.inject(object)

By annotating the constructor by @Inject

Scope

It is possible to create its own scope for its components. We can create a scope @PerActivity which allow to bind a component to an Activity.

Exemple de scope personnalisé

Java

1

2

3

@Scope

@Retention(RUNTIME)

public@interfacePerActivity{}

Gather everything

Installation

In your root build.gradle file add the following dependency:

build.gradle

1

classpath'com.neenbedankt.gradle.plugins:android-apt:1.4'

In your build.gradle app add the following plugin:

build.gradle

1

apply plugin:'com.neenbedankt.android-apt'

and the following dependencies

build.gradle

1

2

3

compile'com.google.dagger:dagger:2.0.1'

apt'com.google.dagger:dagger-compiler:2.0.1'

provided'org.glassfish:javax.annotation:10.0-b28'

Build the graph

Now that we have a module and a component (cf Inside Dagger 2) you can build the dependency graph of your application.

Exemple d'application

Java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

publicclassMyAppextendsApplication{

privateApplicationComponent applicationComponent;

@Override

publicvoidonCreate(){

super.onCreate();

this.applicationComponent=DaggerApplicationComponent

.builder()

.applicationModule(newApplicationModule(this))

.build();

}

publicApplicationComponent applicationComponent(){

returnapplicationComponent;

}

}

Injection

In order to inject your elements in your Activity or your Fragment you must use the property injection.