Dependency Injection on Android

Back when I started writing Android apps in 2009 things were a little different. Apps were a whole new world of software development and everything was evolving, no one took apps too seriously and they were just a bit of fun.
Fast forward to the present day and the mobile app landscape has totally changed. Apps are now big business and are becoming cornerstones of companies strategies. At JUST EAT this is very much the case. We know our customers love using our apps and so we see it as really important that we create apps that are robust and give a fantastic user experience.
So as you may be able to tell, we’re serious about our apps, and serious developers use serious software tools and techniques. One of those software techniques we use in JUST EAT is Dependency Injection and the associated frameworks that go along with it.

It’s just a design pattern

Dependency Injection (DI) is a design pattern which has been around for while, but recently it has become more commonly used in the development of Android applications, due mainly to the implementation of some rather nifty DI frameworks. DI allows developers to write code that has low coupling and which can therefore be easily tested. The more complex and longer lived your Android software the more important it becomes to be able to test it effectively. At JUST EAT we see DI as key to allowing our code to be configurable and therefore testable, so creating a codebase we can have confidence in.  Even though we have a fairly large and complicated codebase, we can make releases regularly and quickly because we have robust testing which is achieved in part by using DI.  With that in mind hopefully I’ve convinced you that DI is worth a look, but first let’s have a quick recap of what DI is.

Basics of Dependency Injection

When we write code we will often find that our classes will have dependencies on other classes. So class A might need to have a reference, or dependency to class B. To make things a little clearer let’s look at the case where we have a Car class that needs to use an Engine class.

public class Car {
    private Engine engine;
    public Car() {
        engine = new PetrolEngine();
    }
}

This code works fine, but the downside is that the coupling between the Car and the Engine is high. The Car class creates the new Engine object itself and so it has to know exactly what Engine it needs, in this case a PetrolEngine. Maybe we could do a little better and reduce the coupling, so let’s look at a different way of creating this Car class.

public class Car {
    private Engine engine;
    public Car(Engine engine) {
        this.engine = engine;
    }
}

Here we have passed the Engine into the Car via the car’s constructor method. This means that the coupling between the two objects is now lower. The car doesn’t need to know what concrete class the Engine is, it could be any type of Engine as long as it extends the original Engine class. In this example since we have passed, or injected, the dependency via the Car classes constructor we have performed a type of injection known as constructor injection, we can also perform injection via methods and with the use of DI frameworks directly into fields. So that’s really all there is to DI. At its most basic it is just passing dependencies into a class rather than instantiating them directly in the class.

If DI is simple, why do we need Frameworks?

Now that we understand what DI is, it’s quite straightforward to start using it in our code. We simply look at what dependencies are needed and pass them via a constructor or a method  call. This is fine for simple dependencies, but you’ll soon find that for more complex dependencies things can start getting a little messy.
Let’s return to our example of a Car that has a dependency on an Engine. Now imagine that the engine also has it’s own set of dependencies. Let’s say it needs a crank shaft, pistons, block and head. If we follow DI principles we will pass these dependencies into the Engine class, that’s not so bad, we just need to create these objects first and pass them into the Engine object when we create that. Finally we pass the Engine to the Car.
Next let’s make our example a little more complicated. If we imagine trying to create classes for each part of an engine we can see that we would soon end up with possibly hundreds of classes with a complicated tree (more accurately it is a graph) structure of dependencies.
di_graph

A simplified graph of dependencies for our example. Here the leaf dependencies have to be created first then passed to the objects that depends on them. All objects have to be created in the correct order.

To create our dependencies we would then have to carefully create all our objects in the correct order, starting with the leaf node dependencies and passing those in turn to each of their parent dependencies and so on until we reach the top most or root dependency.
Things are starting to get quite complicated, if we also used factories and builders to create our classes we can soon see that we have to start creating quite a lot of complicated code just to create and pass our dependencies, this type of code is commonly know as boilerplate code and generally it’s something we want to avoid writing and maintaining.
From our example we can see that implementing DI on our own can lead to creating a lot of  boilerplate code and the more complex your dependencies the more boilerplate you will have to write. DI has been around for a while and so has this problem, so to solve it Frameworks for using DI have been create. These frameworks make it simple to configure dependencies and in some cases generate factory and builder classes for creating objects, making it very straightforward to create complex dependencies that are easily managed.

Which DI framework should I use for Android?

Since DI has been around for a while there are unsurprisingly quite a few DI frameworks that we can choose from. In the Java world we have Spring, Guice and more recently Dagger. So which framework should we use and why?
Spring is a DI framework that’s been around for sometime. It’s aim was to solve the problem of declaring dependencies and instantiating objects. It’s approach was to use XML to do this. The downside to this was that the XML was almost as verbose as writing the code by hand and also validation of it was done at runtime. Spring introduced a number of problems while trying to solve the initial problems of using DI.
In the history of Java DI frameworks, Guice was really the next evolution after Spring. Guice got rid of the XML configuration files and did all of its configuration in Java using annotations such as @Inject and @Provides. Things were starting to look a whole lot better, but there were still some problems. Debugging and tracking down errors with applications built using Guice could be somewhat difficult. Additionally it still did runtime validation of the dependency graphs and also made heavy use of reflection, both of which are fine for server side applications, but can be quite expensive for mobile applications that are launched much more often on devices with much lower performance.
While Guice was a big step forward it really didn’t solve all the problems and its design was also not ideally suited for use on mobile devices. With that in mind a team of developers at a company called Square developed Dagger.
Dagger takes its name from our tree structure of dependencies. Remember more accurately it is a graph of dependencies and in this case the graph is actually a Directed Acyclic Graph or DAG hence the name DAGger. Dagger’s aim was to address some of the concerns of using Guice and especially using Guice on mobile devices.
Dagger took the approach of moving a lot of its workload to compile time rather than runtime and also tried to remove as much reflection from the process as possible, both of which really helped performance when running on mobile applications.  This was done at the slight expense of reducing the feature set offered by the likes of Guice, but for Android apps Dagger was still a step in the right direction. With Dagger we are nearly at a good solution for a DI framework that is suitable for mobile devices, but a team at Google decided that things could still be done a little better and so they created Dagger 2.
Dagger 2 does even more of its work at compile time and also does a better job of removing reflection, finally it also generates code that is even easier to debug than the original version of Dagger. In my opinion there really isn’t a better solution for DI on Android, so if you’re going to use a DI framework, I believe that Dagger 2 really is the easiest to use and debug with, while also having the best performance.

Getting started with DI on Android.

So where do you go from here? Luckily Dagger and Dagger 2 already have a strong following so there are plenty of tutorials and presentation to help you get up to speed.
The main Dagger 2 website can be found here and to get a good overview of Dagger 2 and it features there’s a great presentation by Jake Wharton that you can find here. It covers the basics and then goes on to discuss how Modules and Components work, while also covering the subject of scopes in Dagger 2. Finally to get you firmly on the road to using DI in Android here’s a list of handy tutorials:
Good overview of Dagger 2: http://fernandocejas.com/2015/04/11/tasting-dagger-2-on-android
What is Dagger 2 and how to use it:
http://konmik.github.io/snorkeling-with-dagger-2.html
Scopes in Dagger 2 :
http://frogermcs.github.io/dependency-injection-with-dagger-2-custom-scopes/
Using Dagger 2 with Espresso and Mockito for testing
http://blog.sqisland.com/2015/04/dagger-2-espresso-2-mockito.html

  1. Title suggests a thorough explanation, but after some history of DI the actual content is not there… And most of the links don’t work. So, pretty useless article, sorry to say.

  2. The challenges around DI can be tricky to articulate, this article does a great job of putting that in the mobile app dev context – appreciate the effort to write this, I found it a really useful article.

  3. Thanks its very nice explanation of What is DI and why use Framework and then Why Dagger2 as framework.
    Thanks

Comments are closed.