You are browsing the archive for DI.

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

March 9, 2016 in Android

androidlogo1
In the previous article, we have a quick introduction to Dagger 2 with a simple introductory example. In this article, I will show you how to use Android Build variants with Dagger 2 to have different implementations (for the service interface) that are switched automatically when the app is in the debug mode or in the release mode.

First of all, under the release directory, let’s create a new component DaggerGraphComponent which extends from DaggerGraph as follows.

@Singleton
@Component(modules = {MainModule.class, ServiceModule.class})
public interface DaggerGraphComponent extends DaggerGraph {

    static final class Initializer {
        private Initializer() {
        }

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

Secondly, create a service module which will be responsible for creating the instances of HelloService implementations (in debug and release modes).

For the release mode, ServiceModule provides only an instance of the HelloServiceReleaseManager class which implements HelloService.

@Module
public class ServiceModule {

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

Below is HelloServiceReleaseManager simple implementation.

public class HelloServiceReleaseManager implements HelloService {

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

Apply the same steps under the debug directory, in debug case, you can have a HelloServiceDebugManager class which implements HelloService interface as shown below.

public class HelloServiceDebugManager implements HelloService {

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

Make sure to have the following code hierarchy in release and debug.
Release Directory

Debug Screenshot

Running the project

Now, you can run the app in debug mode, and then enter some name and then click “Greet!” button, you will find the debug service response as follows.
Debug Mode

And then change the build variant to run the app in the release mode and do the same previous steps to see the results as shown below.
Release Mode

Checkout the code

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

What is next?

So in the next article, I will discuss how can we apply unit testing techniques for Dagger 2 applications. Stay tuned!

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

March 5, 2016 in Android

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.

Skip to toolbar