Dependency Injection in Android using Dagger 2 : The concept

What is a dependency?

A Java class has a dependency on another class if it uses an instance of this class. We call this a class dependency. So when you have an object that needs or depends on another object to do its work, you have a dependency.

public class SomeActivity extends Activity {    
private SomeFragement sf;
void onCreate(){
sf = new SomeFragment();
int newId = sf.getId();
}
}
public class SomeFragment extends Fragment {  
int id;
int getId() {
return id
}
}

Here we have an activity which has a dependency on SomeFragment class. Dependencies can be solved by letting the dependent object create the dependency or asking a factory object to make one as shown in code above.

Now when the scale of project increases running unit test on any function which is very highly coupled becomes difficult, requiring instantiating all the dependencies first and creating an inherent dependency chain.

So what is dependency Injection?

In case of dependency injection the dependencies are supplied to the class that needs the dependency to avoid the need for the class itself to create them. This way you create software that is loosely coupled and highly maintainable. Objects are instantiated somewhere else and passed as constructor attributes when creating the current object. This is the basic concept behind dependency injection.

What is Dagger 2?

Dagger 2 is dependency injection framework. It is based on the Java Specification Request (JSR) 330. It uses code generation and is based on annotations. The generated code is very relatively easy to read and debug.

Dagger 2 uses the following annotations:

  • @Module and @Provides: define classes and methods which provide dependencies
  • @Inject: request dependencies. Can be used on a constructor, a field, or a method
  • @Component: enable selected modules and used for performing dependency injection

In Dagger it is not allowed to use private fields for field injection as Dagger uses generated code to access the fields and not reflection. Reflection is awesome, but is very time consuming on low-end devices, and specially on old android versions. Dagger, however, uses a pre-compiler that creates all the classes it needs to work. That way, no reflection is needed.

Why do we need all this mess?
  • Readability and Maintainablity — Well for small scale projects dependency injection might not look all that useful but as the scale of project increases you will need to use dependency injection. Dependency Injection will reduce the amount of boilerplate you have to call to setup your instances with the required dependencies. Less code means improved readability. The price to pay for this is the configuration involved, but, for large scale projects, it’s worth it.
  • Easier unit and integration testing — The dependency graph is created for us, we can easily swap out modules that make network responses and mock out this behavior.
  • Scoped instances — Not only can you easily manage instances that can last the entire application lifecycle, you can also leverage Dagger 2 to define instances with shorter lifetimes (i.e. bound to a user session, activity lifecycle, etc.). How delightful is that? \(*_*)/

These were my 2 cents on dependency injection. More on how to use Dagger 2 to achieve this in my next post. If you have any doubts I am more than happy to clear them.