An Introduction to Dagger 2 (Android DI) – Part 1

androidlogo1
Dagger 2 is a dependency injection framework that is built on the standard javax.inject annotations (JSR 330). Dependency injection is a software design pattern that implements inversion of control for resolving dependencies. Implementing proper dependency injection in our apps allows us to have:

  1. Testable classes.
  2. Re-usable and interchangeable components.

In Android, there are a lot of dependency injection frameworks that you can use. However, one of the greatest advantages of Dagger is that is based on Code generation not on Reflection like Google RoboGuice which makes Dagger more efficient.

In Dagger 2, you can inject dependencies on fields and constructors as shown in the following examples. Injecting dependencies on methods is also possible.

// Field Injection Example
@Inject
HelloService helloService;
// Constructor Injection Example
HelloService helloService;
	
@Inject
public MyClass(HelloService helloService) {
    this.helloService = helloService;
}

In order to understand Dagger, it is important to identify Dagger main terms:

  1. Module.
  2. Component.

Module

Before defining what a Dagger module is and since this is a first basic example to show how Dagger 2 works, assume that we have only one simple service interface (HelloService) that is defined below.

public interface HelloService {
    public String greet(String userName);
}

HelloServiceManager is the simple implementation for HelloService interface as shown below.

public class HelloServiceManager implements HelloService {

    @Override
    public String greet(String userName) {
        return "Hello " + userName + "!";
    }
}

In order to inject HelloService interface implementation, we need to define a Dagger module.

A dagger module provides the way that constructs the objects which will be injected. In order to define a dagger module, create a class and annotate it with @Module annotation and define the provider methods that return the instances. Provider methods have to be annotated by @Provider annotation as shown below.

@Module
public class MainModule {
    DaggerApplication app;

    public MainModule(DaggerApplication application) {
        app = application;
    }

    @Provides
    @Singleton
    protected Application provideApplication() {
        return app;
    }

    @Provides
    @Singleton
    HelloService provideHelloService() {
        return new HelloServiceManager();
    }
}

Here in this module, we provide two singleton instances of an Android application class (DaggerApplication will be discussed later) and the HelloService implementation class.

Component

A dagger component can be seen as an intermediate object which allows accessing to objects defined in Dagger modules.

One of the cool functions of a Dagger component is that it allows injecting non private field members to provided object as argument. In some cases, constructor injection is not possible, for example, the instances that are created and managed by the platform such as Android activity.

This is why we need to create a component interface that allows describing for which types we want to use members injection as shown below.

@Singleton
@Component(modules = {MainModule.class})
public interface DaggerGraphComponent {
    void inject(MainActivity mainActivity);

    static final class Initializer {
        private Initializer() {
        }

        public static DaggerGraphComponent init(DaggerApplication app) {
            return DaggerDaggerGraphComponent.builder()
                                             .mainModule(new MainModule(app))
                                             .build();
        }
    }
}

A dagger component can be created by annotating the class with @Component annotation, you need also to specify the component’s associated modules which is a single module MainModule in our case.

Since we have a single activity, we will have a single inject(MainActivity) method in our Dagger component interface.

Once you annotate your component class with @Component, Dagger will generate a builder class for our component class with the prefix (Dagger). Using the builder class you can initialize the Dagger 2 dependency graph as follows.

DaggerDaggerGraphComponent.builder()
                          .mainModule(new MainModule(app))
                          .build();

Now, let’s see how to initialize dependency graph and consume services.

Initializing Dependency Graph

In order to initialize the Dagger 2 Dependency graph, we need to create an application class to call the component init() method for initializing the Dagger 2 dependency graph and to keep the instance of created graph throughout application’s lifecycle.

The code below shows our Android Application class.

public class DaggerApplication extends Application {
    private static DaggerGraphComponent graph;
    private static DaggerApplication instance;

    @Override
    public void onCreate() {
        super.onCreate();
        instance = this;
        buildComponentGraph();
    }

    public static DaggerGraphComponent component() {
        return graph;
    }

    public static void buildComponentGraph() {
        graph = DaggerGraphComponent.Initializer.init(instance);
    }
}

Do not forget to register the application class in AndroidManifest.xml as follows.

    <application
	...
        android:name=".service.di.DaggerApplication">
	...
    </application>

Injecting HelloService in Activity

Finally, in order to inject HelloService in your activity, do not forget to call DaggerApplication.component().inject(this) in the Activity onCreate() method as shown below.

public class MainActivity extends AppCompatActivity ... {

    @Inject
    HelloService helloService;

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

        DaggerApplication.component().inject(this);	
	// ...
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.greet) {
            // you can call helloService.greet("user1") for example ...
        }
    }
}

Checkout the code

Check the sample app code in GitHub:
https://github.com/hazems/Dagger-Sample/tree/dagger-sample1

What is next?

So in the next articles, I will discuss how Dagger 2 DI can also be very useful if you are utilizing Android Build variants and how can we apply unit testing techniques for Dagger 2 applications.

This entry was posted in Android and tagged , , , , , by Hazem Saleh. Bookmark the permalink.

About Hazem Saleh

Hazem Saleh has more than eleven years of experience in Cloud, Mobile and Open Source technologies. He worked as a software engineer, technical leader, application architect, and technical consultant for many clients around the world. He is an Apache PMC (Project Management Committee) member and a person who spent many years of his life writing open source software. Beside being the author of the "JavaScript Unit Testing" book, "JavaScript Mobile Application Development" book, "Pro JSF and HTML5" book and the co-author of the "Definitive guide to Apache MyFaces" book, Hazem is also an author of many technical articles, a developerWorks contributing author and a technical speaker in both local and international conferences such as ApacheCon North America, Geecon, JavaLand, JSFDays, CON-FESS Vienna and JavaOne. Hazem is an XIBMer, he worked in IBM for ten years. Now, He is working for Nickelodeon New York as a Mobile Architect. He is also an OpenGroup Master Certified Specialist.

One thought on “An Introduction to Dagger 2 (Android DI) – Part 1

  1. Pingback: An Introduction to Dagger 2 (Android DI) - Part 2 | Technical Advices, "An advice can always help"

Comments are closed.