Let’s check Dagger 2 for Android

This is a post for people who tried to learn Dagger2 but have some questions about it. If you have not learned anything about Dagger2 please check the links at the bottom first and then come back!

So I started with RxJava in another post. And I continued researching where does RxJava apply. So I remembered Dagger2. Dagger2 is a dependency injection framework. Dagger1 was developed by Square, Dagger2 was forked and developed by Google. What is Dagger? I wrote an article about Dependency Injection may be a year ago.

Example

Let’s say you have a class which access your database and has query methods. You have 2 activities. What do you do if you want to use this class? MyClass myClass = new MyClass() – and this is in two places. What happens if you have 20 activities? And now you want to get your data from both the cache and the db, whichever loads first. You have to add some methods to the class and it now makes your life harder than ever. So this is where Dependency Injection comes in. You say in your constructor “I want to have this and this class given to me when you want to instantiate me” and you don’t care who and how will provide you the classes you need. Of course you can expect to receive an instance implementing a given interface and you should be working with interfaces all the time. And Dagger helps you automate the injection of classes which implement given interfaces.

How does it work?

Dagger has components, sub-components, scopes and modules. And the learning curve is so steep. Many of the examples on the web include Dagger1, they don’t explain some things like why components are interfaces, why are they needed, when to use scope and why, what is the difference between sub-components and dependencies. I will try to be short and make some things clear here.

Modules

The are classes with the @Module annotation. They provide the implementation of the classes you want to inject. The naming convention requires you to name your method: providesMyClass() with a @Provides annotation over the method. A providesMyClass() method can accept parameters, which will be automatically injected from Dagger if it knows about the implementation and where it can be found. Enough said.

class ApplicationModule {
  Application application;

  // Initially there is nowhere from where you can get the Application.
  // That is why you need to manually inject it
  ApplicationModule(Application application) {
    this.application = application;
  }

  @Provides
  public Application providesApplication() {
    return application;
  }

  @Provides
  public SharedPreferences providesSharedPreferences() {
    return PreferenceManager.getDefaultSharedPreferences(application);
  }
}

Components

Edit: In Dagger2 there is a new way declaring dependencies. You can check it here: https://github.com/frogermcs/Dagger2Recipes-ActivitiesMultibinding

They are interfaces in which you declare what are the classes which your module provides.

Why are they interfaces and why are they needed? Because Dagger1 had some reflection used to build the graph of dependencies. Dagger2 does not use reflection at all. That requires the usage of the “new” @Components annotation.

Now, turn on your imagination. Imagine a graph with a single root at top. This is your Application class. It is the almighty king of all. You want to say to Dagger: “Hey, this is my main class, it provides GSON, SharedPreferences, WebAPI connection and they should be available for all activities.”. What you do is you create an Application component with a module providing these classes. Then you say: “Hey, I want to share the current activity, which should be available for all fragments, who are used within an activity”. So now you make an Activity component, which depends on the Application component, but makes sure that other classes that use the application class, don’t have access to it.  Now you have 1 root with 1 node. Root – Application, Node – Activity. Nice, huh?

There are 2 ways to build the graph. Using components with the @Component(dependencies=…) or with sub-component. You can check the article at the bottom to see which to use when. I wanted to tell you that each time you say dependencies=MyClass2.class, you have access to the classes declared in the MyClass2Component interface. That means you build a node which is extending MyClass2Component. If you use sub-components you don’t need to have the dependencies declaration, sub-components can access their parent’s dependencies.

  @Component(modules=ApplicationModule.class)
  interface ApplicationComponent {
    // This component won't declare that it provides SharedPreferences.
    // Because it does not have a method declaration
    Application getApplication()
  }


  @Module
  class ActivityModule {
    @Provides
    String providesUserName(SharedPreferences prefs) {
      return prefs.getString(...);
    }
  }

  // Now we have Application (ROOT) -> Activity (NODE)
  // This component has access to Application but does not have to SharedPreferences
  // because it is not declared in the ApplicationComponent interface
  @Component(modules=ActivityModule.class, dependencies=ApplicationComponent.class)
  interface ActivityComponent {
    // It should generate an error that it does not find SharedPrefs
    String getUserName()
  }

Scopes

In Dagger 2 scopes mechanism cares about keeping single instance of class as long as its scope exists. Just read THIS question carefully. Now you got it, don’t you? Scopes determine how long an instance of a class should be used. You want to use SharedPreferences during the app lifetime, but you don’t want to use the same activity dependencies when the activity changes.

Links

http://google.github.io/dagger/
Creators Video – tells why you need to have an interface just to declare what component you need.
Jake Wharton from Square
Making a Best Practice App
DI with Dagger2
Another post about Dagger2
What the hell is Dagger?
DI for Android Developers
Scopes
More Scopes
Vogella FTW
More more Dagger
Docs from Google – Components vs Sub-components
And More Sub-components
Component dependencies vs Subcomponents?

Briefly, if you did not get anything from here write a comment or watch and read all the links I provided. I already did and it took me 4-5 days just looking and trying. Afterwards it becomes nice and simple. Give it a try and share your results with me. I hope I have helped!

P.S. I still have the notion that Dagger2 is not a Dependency injection framework. You say at so many places: “Dagger…myModule().build()”. This couples it tightly with the class built from Dagger. In Ninject you could have all the configuration in one place and let it inject the correct interface implementation without having you write strange generated stuff. 🙂

 

You may also like...