Home Tutorials Training Consulting Products Books Company Donate Contact us









NOW Hiring

Quick links

Share

This article describes the usage of Dagger 2 within standard Java applications and within Android applications.

1. Introduction to the concept of dependency injection

See Dependency Injection for an introduction into the concept of dependency injection.

2. Dependency injection with Dagger 2

2.1. What is Dagger 2?

Dagger 2 is dependency injection framework. It is based on the Java Specification Request (JSR) 330. It uses code generation and is based on annotations. The generated code is very relatively easy to read and debug.

Dagger 2 uses the following annotations:

  • @Module and @Provides: define classes and methods which provide dependencies

  • @Inject: request dependencies. Can be used on a constructor, a field, or a method

  • @Component: enable selected modules and used for performing dependency injection

Dagger 2 uses generated code to access the fields and not reflection. Therefore it is not allowed to use private fields for field injection.

2.2. Defining dependency providers (object providers)

The term dependency injection context is typically used to describe the set of objects which can be injected.

In Dagger 2, classes annotated with @Module are responsible for providing objects which can be injected. Such classes can define methods annotated with @Provides. The returned objects from these methods are available for dependency injection.

Methods annotated with @Provides can also express dependencies via method parameters. These dependencies are fulfilled by Dagger 2, if possible.

2.3. Defining dependencies (object consumers)

You use the @Inject annotation to define a dependency. If you annotate a constructor with @Inject, Dagger 2 can also use an instance of this object to fulfill dependencies. This was done to avoid the definition of lots of @Provides methods for these objects.

2.4. Connecting consumers and providers

The @Component is used on an interface. Such an interface is used by Dagger 2 to generate code. The base pattern for the generated class is that Dagger is used as prefix followed by the interface name. This generate class has a create method which allows configuring the objects based on the given configuration. The methods defined on the interface are available to access the generated objects.

A @Component interface defines the connection between provider of objects (modules) and the objects which expresses a dependency. The following table gives an overview of the usage of the Dagger annotations.

Table 1. Annotation summary of Dagger 2
Annotation Usage

@Module

Used on classes which contains methods annotated with @Provides.

@Provides

Can be used on methods in classes annotated with @Module and is used for methods which provides objects for dependencies injection.

@Singleton

Single instance of this provided object is created and shared.

@Component

Used on an interface. This interface is used by Dagger 2 to generate code which uses the modules to fulfill the requested dependencies.

2.5. Scope annotations

You can use the @Singleton annotation to indicate that there should be only one instance of the object.

2.6. Special treatment of fields in Dagger

Dagger 2 does not inject fields automatically. It can also not inject private fields. If you want to use field injection you have to define a method in your @Component interface which takes the instance into which you want to inject as parameter.

2.7. Using Dagger 2 with Eclipse and Maven

To use Eclipse and Maven together with Dagger 2 you can install the Maven tooling and the apt plug-in which allows Maven to configure the annotation processors.

For Eclipse Maven support use the update site of your release and afterwards install the m2e-apt tooling via the http://download.jboss.org/jbosstools/updates/m2e-extensions/m2e-apt update site.

After the installation you must enable apt-processing on via the Eclipse preferences in Window ▸ Preferences ▸ Maven ▸ Annotation Processing. Select Automatically configure JDT APT.

Maven apt processing configuration

3. Exercise: Dependency injection with Dagger 2

In this example you use Dagger 2 in a standard Java program managed by Maven.

This exercise can be done via any Java IDE you like, for example the Eclipse IDE with the Maven tooling installed. Or it can be developed and compiled via a text editor and the Maven command line. If you use Eclipse, ensure to install the Eclipse Maven tooling.

3.1. Create example project for the usage of Dagger 2

Create a new Maven project with the com.vogella.java.dagger2 top level package.

3.2. Define or adjust Maven build file

Adjust your pom.xml to the following.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.vogella.java.dagger2</groupId>
    <artifactId>com.vogella.java.dagger2</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>com.vogella.java.dagger2</name>

    <dependencies>
        <dependency>
            <groupId>com.google.dagger</groupId>
            <artifactId>dagger</artifactId>
            <version>2.4</version>
        </dependency>
        <dependency>
            <groupId>com.google.dagger</groupId>
            <artifactId>dagger-compiler</artifactId>
            <version>2.4</version>
            <optional>true</optional>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.3</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

3.3. Define classes which have a dependency

Define the following two classes which express dependencies.

package com.vogella.java.dagger2;

import javax.inject.Inject;

public class User {

        private String firstName;
        private String lastName;

        public User(String firstName, String lastName) {
                this.firstName = firstName;
                this.lastName = lastName;
        }

        @Override
        public String toString() {
                return "User [firstName=" + firstName + ", lastName=" + lastName + "]";
        }
}
package com.vogella.java.dagger2;

import javax.inject.Inject;

public class BackendService {

        @Inject
        public User user;

        private String serverUrl;

        @Inject
        public BackendService(@Named("serverUrl") String serverUrl) {
                this.serverUrl = serverUrl;
        }

        public boolean callServer() {
                if (user !=null && serverUrl!=null && serverUrl.length()>0) {
                        System.out.println("User: " + user + " ServerUrl: "  + serverUrl);
                        return true;
                }
                return false;
        }
}

3.4. Define modules which provides dependencies

Define two class which acts as providers for dependencies.

package com.vogella.java.dagger2.modules;

import javax.inject.Named;
import javax.inject.Singleton;

import com.vogella.java.dagger2.BackendService;

import dagger.Module;
import dagger.Provides;

@Module
public class BackEndServiceModule {

    @Provides
    @Singleton
    BackendService provideBackendService(@Named("serverUrl") String serverUrl) {
       return new BackendService(serverUrl);
    }

    @Provides
    @Named("serverUrl")
    String provideServerUrl() {
       return "http://www.vogella.com";
    }

    @Provides
    @Named("anotherUrl")
    String provideAnotherUrl() {
       return "http://www.google.com";
    }

}
package com.vogella.java.dagger2.modules;

import javax.inject.Singleton;

import com.vogella.java.dagger2.User;

import dagger.Module;
import dagger.Provides;

@Module
public class UserModule {

    @Provides
    @Singleton
    User providesUser() {
            return new User("Lars", "Vogel");
    }
}

3.5. Define components

Components define from which modules (or other components) dependencies are provided. Dagger 2 uses this interface to generate the accessor class which provides the methods defined in the interface.

package com.vogella.java.dagger2.component;

import javax.inject.Singleton;

import com.vogella.java.dagger2.BackendService;
import com.vogella.java.dagger2.modules.BackEndServiceModule;
import com.vogella.java.dagger2.modules.UserModule;

import dagger.Component;

@Singleton
@Component(modules = { UserModule.class, BackEndServiceModule.class })
public interface MyComponent {

    // provide the dependency for dependent components
    // (not needed for single-component setups)
        BackendService provideBackendService();

        // allow to inject into our Main class
        // method name not important
        void inject(Main main); (1)
}
1 Method which allows injecting into BackendServer for the fields

3.6. Use the generated dagger code

The usage of the generated code is demonstrated by the following test class.

package com.vogella.java.dagger2.main;

import com.vogella.java.dagger2.BackendService;
import com.vogella.java.dagger2.component.DaggerMyComponent;
import com.vogella.java.dagger2.component.MyComponent;

public class Main {

    @Inject
    BackendService backendService; // (1)

    private MyComponent component;

    private Main() {
        component = DaggerMyComponent.builder().build();
        component.inject(this);
    }

    private void callServer() {
        boolean callServer = backendService.callServer();
        if (callServer) {
            System.out.println("Server call was successful. ");
        } else {
            System.out.println("Server call failed. ");
        }
    }

        public static void main(String[] args) {
        Main main = new Main();
        main.callServer();
        }
}
1 Fields are not automatically injected hence the method call to inject the fields

4. Dagger 2 and Android

4.1. Using dependency injection with Android

Many Android components, e.g. activities, are instantiated by the Android framework and not in your code. This makes it difficult to supply dependencies via constructors to Android components.

4.2. Using Dagger 2 in Android

To enable Dagger 2 add the following dependencies to your build.gradle file.

compile 'com.google.dagger:dagger:2.10'
annotationProcessor 'com.google.dagger:dagger-compiler:2.10'

If you want to use classes from the dagger.android package, like DaggerActivity, also add the following dependencies to your build.gradle file. This is also needed, if you want to inject Activities components like activities or fragments.

compile 'com.google.dagger:dagger-android:2.10'
annotationProcessor 'com.google.dagger:dagger-android-processor:2.10'

If you want to use the support libraries with Dagger 2, you also have to add the following to your build.gradle

compile 'com.google.dagger:dagger-android-support:2.10'

5. Exercise: Dependency injection in Android activities with Dagger 2

In this exercise the usage of the Dagger 2 dependency injection framework in an Android application is demonstrated . In our simple app, there is an activity that allows a user to authenticate some credentials. The result value of the implementation is displayed in a text field.

5.1. Create project

Create a new project called com.vogella.android.dagger2simple with the top level package com.vogella.android.dagger2simple.

5.2. Enter Gradle dependencies

Add the following dependencies to your build.gradle file.

compile 'com.google.dagger:dagger:2.10'
compile 'com.google.dagger:dagger-android:2.10'
annotationProcessor 'com.google.dagger:dagger-android-processor:2.10'
annotationProcessor 'com.google.dagger:dagger-compiler:2.10'

5.3. Define your dependency graph

As mentioned above, Android components (activities, fragments, etc.) are instantiated by the Android framework which makes it difficult to use dependency injection on them. Fortunately, Dagger provides classes that simplifies the dependency injection into Android components. This requires a little setup work to get your application running.

First, create a class named NetworkApi. This class is used to inject it into an activity.

package com.vogella.android.dagger2simple;

import javax.inject.Inject;

public class NetworkApi {

    @Inject
    public NetworkApi(){
    }

    public boolean validateUser(String username, String password) {
        // imagine an actual network call here
        // for demo purpose return false in "real" life
        if (username == null || username.length() == 0) {
            return false;
        } else {
            return true;
        }
    }
}

With the @Inject annotation for the constructor, we tell Dagger that an object of this class is injectable into other objects. Dagger automatically calls this constructor, if an instance of this class is requested.

Adjust your activity to receive an instance of NetworkApi. This demonstrates the dependency injection with the NetworkApi.

package com.vogella.android.dagger2simple;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

import javax.inject.Inject;

import dagger.android.AndroidInjection;

public class MainActivity extends Activity {

    @Inject NetworkApi networkApi;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        AndroidInjection.inject(this);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        boolean injected =  networkApi == null ? false : true;
        TextView userAvailable = (TextView) findViewById(R.id.target);
        userAvailable.setText("Dependency injection worked: " + String.valueOf(injected));
    }
}

The activity layout file should look similar to the following.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/target"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" />

</RelativeLayout>

Now, create an interface with the name IMainActivitySubcomponent.

package com.vogella.android.dagger2simple.components;

import com.vogella.android.dagger2simple.MainActivity;

import dagger.Subcomponent;
import dagger.android.AndroidInjector;

@Subcomponent
public interface IMainActivitySubcomponent extends AndroidInjector<MainActivity> {

    @Subcomponent.Builder
    abstract class Builder extends AndroidInjector.Builder<MainActivity> {}
}

This interface represents a Dagger subcomponent which is able to inherit bindings from any parent (sub-)component. It extends the AndroidInjector to perform member injection on a concrete Android component type (in our case MainActivity) and also specifies the corresponding builder.

To add your subcomponent to a parent component create a module named ActivityModule like the following.

package com.vogella.android.dagger2simple.modules;

import android.app.Activity;

import com.vogella.android.dagger2simple.MainActivity;
import com.vogella.android.dagger2simple.components.IMainActivitySubcomponent;

import dagger.Binds;
import dagger.Module;
import dagger.android.ActivityKey;
import dagger.android.AndroidInjector;
import dagger.multibindings.IntoMap;

@Module(subcomponents = {IMainActivitySubcomponent.class})
public abstract class ActivityModule {

    @Binds
    @IntoMap
    @ActivityKey(MainActivity.class)
    abstract AndroidInjector.Factory<? extends Activity> bindYourActivityInjectorFactory(IMainActivitySubcomponent.Builder builder);
}

With the help of the subcomponents parameter in the @Module annotation, the subcomponent is made available to every component that uses the ActivityModule. This class offers an abstract method that binds the builder of the subcomponent to the AndroidInjector.Factory.

If you have a class that you want to make injectable and you are not allowed to change it (to annotate the constructor), you have the possibility to provide a new static method to your module that returns an instance of that class to make it injectable. If you prefer this way, remove the @Inject annotation from the NetworkApi constructor, and add the following lines to your ActivityModule class.

        @Provides
    static NetworkApi provideNetworkApi(){
        return new NetworkApi();
    }

Next, create an interface called IApplicationComponent. This component is responsible for injecting the Application class.

package com.vogella.android.dagger2simple.components;

import com.vogella.android.dagger2simple.MyApplication;
import com.vogella.android.dagger2simple.modules.ActivityModule;

import dagger.Component;
import dagger.android.AndroidInjectionModule;

@Component(modules = {ActivityModule.class, AndroidInjectionModule.class})
public interface IApplicationComponent {
    void inject(MyApplication application);
}

In the @Component annotation the modules are specified which are used to create the implementation of the component. Here, we now add our ActivityModule and therefore also make use of our subcomponent. While we reference our ActivityModule to inject activities, we also reference the AndroidInjectionModule which is needed to ensure the binding of the Android base types (Activities, Fragments, etc.).

5.4. Create your Application class

Create a class named MyApplication that extends Application and implements HasDispatchingActivityInjector like the following.

package com.vogella.android.dagger2simple;

import android.app.Activity;
import android.app.Application;

import com.vogella.android.dagger2simple.components.DaggerIApplicationComponent;

import javax.inject.Inject;

import dagger.android.DispatchingAndroidInjector;
import dagger.android.HasDispatchingActivityInjector;

public class MyApplication extends Application implements HasDispatchingActivityInjector {
    @Inject DispatchingAndroidInjector<Activity> dispatchingAndroidInjector;

    @Override
    public void onCreate() {
        super.onCreate();
        DaggerIApplicationComponent.create().inject(this);
    }

    @Override
    public DispatchingAndroidInjector<Activity> activityInjector() {
        return dispatchingAndroidInjector;
    }
}

Here, we use our IApplicationComponent (now prefixed with Dagger) to inject our Application class. This way a DispatchingAndroidInjector is injected which is then returned when an injector for an activity is requested (through activityInjector()). This injector uses the AndroidInjector.Factory which comes from the ActivityModule to find the corresponding builder of the activity (IActivitySubcomponent.Builder). It then creates the concrete AndroidInjector (in our case IActivitySubcomponent) which can then be used to inject an activity.

Of course the Application class needs to registered via the manifest like the following.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.vogella.android.dagger2simple" >

    <application
        android:name=".MyApplication"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

5.5. Validate

Run your application, the user interface should report that dependency injection worked. If not, have a look at the generated classes in the app/build/generated/apt folder. The generated classes by Dagger are well structured and should give a hint what went wrong.

Running application

6. Replacing @Module classes in tests

For tests you can your custom modules and setup Dagger to use them. The generated builder of Dagger contains methods to set the module. You can use the Dagger build to replace the generated class with the one which should be used for testing.

This also works well with Mockito. Assume you have the following class you want to test.

public class ImportantClass {
    private MyRestService restService;
    private MyLogger logger;

    @Inject public MainService(MyRestService restService, MyLogger logger) {
        this.restService = restService;
        this.logger = logger;
    }

    public void perform() {
        String s = restService.getData();
        logger.write(s.toUpperCase());
    }
}

You can test this class with Mockito.

public class ImportantClassTest {

public class MainServiceTest {

    @Rule public MockitoRule mockitoRule = MockitoJUnit.rule();

    @Mock MyRestService restService;

    @Mock MyLogger logger;

    @InjectMocks ImportantClass importClassToBeTested;

    @Test
    public void performShouldWriteOutput() {
        when(restService.getData()).thenReturn("abc");

        importClassToBeTested.perform();

        verify(logger).print("ABC");
    }
}
}

Better support for replacing Dagger dependencies is offered by https://github.com/fabioCollini/DaggerMock.

7. About this website

8. Dagger resources

8.1. vogella GmbH training and consulting support

TRAINING SERVICE & SUPPORT

The vogella company provides comprehensive training and education services from experts in the areas of Eclipse RCP, Android, Git, Java, Gradle and Spring. We offer both public and inhouse training. Whichever course you decide to take, you are guaranteed to experience what many before you refer to as “The best IT class I have ever attended”.

The vogella company offers expert consulting services, development support and coaching. Our customers range from Fortune 100 corporations to individual developers.

Copyright © 2012-2016 vogella GmbH. Free use of the software examples is granted under the terms of the EPL License. This tutorial is published under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Germany license.

See Licence.