-
Notifications
You must be signed in to change notification settings - Fork 2
Dependency Injection with Dagger 2
Dependency injection is a software design pattern where there are objects (clients) that have a dependency on other or others (services). This dependency it is passed to the dependent object by an injection.
The client delegates to external code (the injector) the responsibility of providing its dependencies. The client is not allowed to call the injector code. It is the injecting code that constructs the services and calls the client to inject them. This means the client code does not need to know about the injecting code. The client does not need to know how to construct the services. The client does not need to know which actual services it is using. The client only needs to know about the intrinsic interfaces of the services because these define how the client may use the services. This separates the responsibilities of use and construction.
There are three common means for a client to accept a dependency injection: setter-, interface- and constructor-based injection. Setter and constructor injection differ mainly by when they can be used. Interface injection differs in that the dependency is given a chance to control its own injection. All require that separate construction code (the injector) take responsibility for introducing a client and its dependencies to each other.
Said that we can get to the conclusion that dependency injection brings us important benefits:
- Since dependencies can be injected and configured externally we can reuse those components.
- When injecting abstractions as collaborators, we can just change the implementation of any object without having to make a lot of changes in our codebase, since that object instantiation resides in one place isolated and decoupled.
- Dependencies can be injected into a component: it is possible to inject mock implementations of these dependencies which makes testing easier.
Basis
Dagger 2 is a fork from Dagger 1 under heavy development by Google, currently version 2.0. This library helps us to write cleaner code and is based on annotations. So here we list the most important:
@Inject: Basically with this annotation we request dependencies. In other words, you use it to tell Dagger that the annotated class or field wants to participate in dependency injection. Thus, Dagger will construct instances of this annotated classes and satisfy their dependencies.
@Module: Modules are classes whose methods provide dependencies, so we define a class and annotate it with @Module, thus, Dagger will know where to find the dependencies in order to satisfy them when constructing class instances. One important feature of modules is that they have been designed to be partitioned and composed together (for instance we will see that in our apps we can have multiple composed modules).
@Provide: Inside modules we define methods containing this annotation which tells Dagger how we want to construct and provide those mentioned dependencies.
@Component: Components basically are injectors, let’s say a bridge between @Inject and @Module, which its main responsibility is to put both together. They just give you instances of all the types you defined, for example, we must annotate an interface with @Component and list all the @Modules that will compose that component, and if any of them is missing, we get errors at compile time. All the components are aware of the scope of dependencies it provides through its modules.
@Scope: Scopes are very useful and Dagger 2 has has a more concrete way to do scoping through custom annotations. We will see an example later, but this is a very powerful feature, because as pointed out earlier, there is no need that every object knows about how to manage its own instances. A scope example would be a class with a custom @PerActivity annotation, so this object will live as long as our Activity is alive. In other words, we can define the granularity of your scopes (@PerFragment, @PerUser, etc).
@Qualifier: We use this annotation when the type of class is insufficient to identify a dependency. For example in the case of Android, many times we need different types of context, so we might define a qualifier annotation “@ForApplication” and “@ForActivity”, thus when injecting a context we can use those qualifiers to tell Dagger which type of context we want to be provided.
Start coding
To start with Dagger 2 follow this tutorial form Vogella.
Also read the documentation here.