Learn Android Dependency Injection with Dagger 2

Shares
Learn Dagger 2

Lately, it is hard to browse through Android tutorials without an article on Dagger 2 or MVP starring at you. In this post, I will share with you a practical definition and example of Dagger 2 and in an upcoming post, I will share with you a to the point example of MVP.

What is Dependency Injection

At a basic level, Dependency Injection encourages flexibility. The term was coined by Martin Fowler in an article about Inversion of Control pattern. A simple example of Dependency Injection is recipes – take a recipe for coffee for example. You can define the ingredients for a cup of coffee like this:

  1. 6 table spoon of dark coffee,
  2. 1 cup of water,
  3. 1 table spoon of Splenda (a type of sweetener) and
  4. 1 teaspoon of vanilla flavored cream.

This recipe can work in most cases, however if someone prefers a caramel flavored cream, a new set of recipe has to be made and if someone prefers a different type of sweetener likewise a new recipe has to be made because the original recipes was defined with concrete ingredients. We can however update our coffee recipe with generic ingredients like this:

  1. 6 table spoon of coffee,
  2. 1 cup of water,
  3. 1 table spoon of sweetener
  4. 1 teaspoon of cream

This now makes our recipe flexible, the actual type of cream or sugar used will be determined or rather injected at the time the coffee is made. This gives the flexibility to for example use mock ingredients during training and switch to real ingredients during production.

The power of dependency injection shines with (sticking with the coffee analogy) if you now want to make cappuccino which requires or depends on some coffee input. The recipe for the cappuccino can be based on the flexible coffee recipe.

Yet another special drink can also be made which requires or depends on cappuccino. So that means three layers of dependencies. With Dependency Injection pattern, the generic ingredients, will be replaced (or injected) with concrete ingredients by the bartender  just in time before serving the coffee.

How does this apply to Android Development

This applies to Android development in two ways: one we as developers drink lots of coffee on average and two Android is a complex web of dependencies.  The code we write often depend on libraries which has dependencies on other libraries.

Context and SharedPreference are good examples of this as we will see shortly in the example that comes with this tutorial. Without Dependency Injection, you are limited to using SharedPreference in only files that inherit from Context aka Activity and Fragments because new instance of SharedPreference has a dependency on Context.

Without getting into MVP in this post, I can say that it makes life easy if you extract your application logic including data persistence from Fragments and Activities into POJO classes aka Presenters. Since these POJO classes do not have Context, how do you get access to SharedPreference which has a dependency on Context? The answer is Dependency Injection – specifically we use Dagger 2 to inject SharedPreference to any class that needs it as you will see in the example that follows. So let us take a look at Dagger 2 next.

What Exactly does Dagger 2 Do

Before we look at what exactly Dagger 2 does, I will like to say that the good thing about Dagger 2 is that it is not magical. Everything it does, at-least the part that you are concerned with is prescriptive. That means you prescribe to Dagger 2 what goes where via annotations. So what does Dagger 2 do? It is a factory that creates and manages your dependency for you based on your specification.

Going back to the coffee analogy, Dagger 2 can be likened to a vending machine that stands near the bartender and creates new copies of the concrete ingredient needed by the bartender to make coffees based on the checklist provided to it.

The checklist must be clear, for example if it specifies that when the recipe calls for 1 table spoon of cream, it should also say what should be the concrete implementation that should be created to satisfy that requirement. Dagger 2 does not make the decision of what object to use to satisfy a dependency for you, that is why I said that it is not magical. You have to specify that upfront. Let’s see this in an example.

Dagger 2 By Example

In this example we are going to create a Java class file called ShoppingCart.java, this file is used in an Android shopping cart app. Part of the work of this ShoppingCart class file is to remember the items that the users add the shopping cart in case there is a configuration change aka phone call came in before they complete their shopping session by checking out.  In the web there is cookies where this kind of temp information can be stored but in Android we have SharedPreference for such a time like this.

Since this ShoppingCart.java file is a humble plain old Java object (POJO) we need to use Dagger 2 to inject SharedPreference to it. Follow the steps below to complete the tutorial. If you are feeling fired up about Dagger 2 and want to see other practical examples, you may want to be notified about my upcoming course Pronto SQLite.

Step 1 – New Project Creation

  1. Create a brand new Android, you can also add this to an existing Android Studio project if you choose to. I am going to name my project ProntoShopApp and select the defaults and click finish.
  2. At the root of the project, create the following class files
    1. ShoppingCart.java – we have talked about this class already, so it should be obvious what is its mission. Next is
    2. ProductPresenter.java – yet another mention of Presenter, don’t worry I will cover MVP in another post, but just know that it is nothing but a Java class file.
    3. At the root of the project, create a package called dagger and add the following class files to the package
      1. AppComponent.java – Component is one of the three legs upon which Dagger 2 stands, this is simply an interface that does two things:
        1. It lists the Dagger Modules in this app.
        2. It lists injectable targets, for example we need SharedPreference in our ShoppingCart.java class, so it is an injectable object that we must specify in the AppComponent.
      2. AppModule.java – Module is another one of the three leg that Dagger 2 stands upon. This is a standard Java class that will be decorated with Dagger 2 specific annotations and it is the methods in this class that provide the dependecies. This particular module provides the Context.
      3. ShoppingCartModule.java – this class is another module what will provide – you guessed it instances of ShoppingCart.
  3. At the root of the application add a package called model and add the following class files to this package
    1. Product.java – this defines the products that we will the app will sell
    2. LineItem.java – this extends product to add price
  4. At the root of the project add file called ProntoShopApplication.java – this will extend from Application.
  5. Update the name of the Application in Manifest.xml to reflect the name of the class you just added ProntoShopApplication.java
  6. The Source code for this sample project can be found here.
  7. Share – If you have found this post useful, please share with someone who can benefit from it.

Step 2 – Add Dagger 2

  1. In your Project build.gradle, add the following line – classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' this will help Android Studio to recognize Dagger 2 generated code. Your Project gradle file should now look like this:
  2. In your module build.gradle file, add the highlighted lines of code
  3. Build your project
  4. Remember to update your applicationId in case you just copied the above line of code and paste.

Step 3: Update Models

  1. Update Product.java with the following code and then use Android Studio Code->Generate->Getter and Setter to generate the boiler plate getter/setter code.
  2. Update LineItem.java with the following code and then also use Android Studio to generate the required boiler plate getter/setter code.

Step 4: AppModule Class

Update your AppModule.java class with the code below. We are now beginning to leverage Dagger 2. Make sure that your ProntoShopApplication.java extends the Application class. Notice the @Module annotation at the top of the class. That is what signifies to Dagger 2 that this is a Module. And what do Modules do again you may ask. Modules in Dagger 2 contain methods which are essentially advanced switch statements. So here we are saying, case Context: return the Application class. It is best practices to name those method names that begin with provide.

Step 5: Update the ShoppingCart Module

Same with the AppModule.java we are annotating this class with @Module annotation. We are saying wherever in our application that we need the ShoppingCart, create a new instance of the ShoppingCart and since the ShoppingCart has a dependency on SharedPreference go ahead and satisfy that dependency by asking the PreferenceManager. And since the PreferenceManager has a dependency on Context before it can fulfill the request for a SharedPreference, Dagger 2 now knows to go to our AppModule and satisfy that dependency by returning our Application class.

Don’t worry about the red lines in Shopping Cart, we will address that shortly.

Step 6: Update the Injector Class

Modules are potential dependency resolvers, however before they can be deployed Dagger 2 needs to know which objects are inject-able targets and it need to get a list of Modules that are providing dependency solutions. We provide these two information in the AppComponent.java class like so: Notice that it has the list of our two modules and the classes that we may need a dependency to be injected.

Step 7: Update the Shopping class

Your Cart logic could be as complex as your business needs demands, here is a sample implementation that demonstrates saving the cart content to the SharedPreference.

Step 8: Update the Application Class

This is the last and very important step, if you copy the code below and paste into your application class you will get compiler error. Why? Because the DaggerComponent has not been created. You remember that our AppComponent is nothing but an Interface, and you remember that the power of an interface lies in the implementation class. Dagger creates the concrete implementation using the @ annotations that we supplied and adds the prefix to Dagger to them so our AppComponent which is an interface will now have a concrete implementation called DaggerAppComponent.

Update your Application class like so:

Step 9 – Put Dagger 2 to Good Use

Now that we have everything wired up, we can actually use Dagger 2 like this .

Conclusion

There you have a it, a practical introduction to Dagger 2 dependency injection framework. This is barely scratching the surface on the immense possibilities that this tool provides. The post should help you get started using Dagger and you will get clarity as you pound the keyboard because code answereth all things.

If you have found value in this post, please use the social media buttons to share this post as it may benefit another Android developer. The source code for this sample project can be found here.

About the Author valokafor

I am a Software Engineer with expertise in Android Development. I am available for Android development projects.

follow me on:
10 comments

Comments are closed