Dagger-Android-Part 3

Dheeraj Andra
MindOrks
Published in
4 min readApr 27, 2019

Welcome to the Part 3 of this Dagger series. In the previous parts, we have learnt about Dependency Injection basics, annotation processing, usage of @Qualifier and @Scope in Dagger.

If you haven’t already gone through Part 1 as and Part 2, I would request you to go through them for better understanding of Dagger in the upcoming parts.

In this part of the series, we are going to look at the main annotations that are provided by the javax.inject package for Dagger. There are mainly four annotations that we are going to see in this part of the series. They are

  • @Module
  • @Provides
  • @Inject
  • @Component

Let’s discuss these annotations one by one.

As discussed in the previous part, when a particular annotation is being used, let us understand its usage by looking at its respective source code.

Module

If we have a look at the source code of Module annotation, it contains the main statement as follows :

....
/**
* Annotates a class that contributes to the object graph.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Module {
/**
...

So, this annotation is used on a class that contributes to the object graph, here it is the Dagger graph or the dependency graph.

What is object/Dagger/Dependency graph here?

The Dependency graph is the graph that is created by Dagger which contains all the instances of the application that need to be injected at the required time. This graph is generated at compile time.

Now, let’s come back to our @Module annotation. This is used on any class that contributes to the Dependency graph. That means, it is used on any class that “provides” the dependency instance that can be used by Dagger to “inject” wherever necessary.

How is a dependency instance ‘provided’ or ‘injected’ ? Well, don’t worry. We’ve seen only one annotation so far. You will understand this when we complete this part of the series.

For now, just understand that @Module is used on any class that helps in providing the Dependency instance.

Provides

Let’s have a look at the source code of this annotation first.

....
/**
* Annotates methods of a {
@linkplain Module module} to create a provider method binding. The
....
@Documented @Target(METHOD) @Retention(RUNTIME)
public @interface Provides {
}

So, from the source code it is evident that this @Provides annotates methods of the Module class to create a provider method for binding. So let’s say Class A needs the instance of Class B. So here, there shall be a configuration class, let’s say Class C.

Class C will contain a method that returns Class B. Hence, the method that is returning Class B should be annotated with @Provides annotation.

Since this class is providing an instance of class B, it is contributing to the Dependency graph and hence should be annotated with @Module

@Module
class classC {
@Provides
fun classBProvider(): classB {
return classB()
}
}

Inject

Let’s have a look at the source code of Inject annotation

.....
/**
* Identifies injectable constructors, methods, and fields.
....
@Target({ METHOD, CONSTRUCTOR, FIELD })
@Retention(RUNTIME)
@Documented
public @interface Inject {}

Note: The source codes mentioned here just represents the basic definition of annotations. To know more about the same, it is highly recommended to go through the entire source code.

So, from the definition, this annotation is used when the necessary instance that needs to be used in a respective class is not defined (to avoid tight coupling) and needs to be injected.

In our above example, since Class B instance needs to be used in Class A. There should be a field in Class A with @Inject annotation as follows:

@Inject
lateinit var
instanceB: ClassB

So, when the Inject annotation is seen, Dagger looks for its corresponding @Provides method that returns a classB instance. Here, the method is classBProvider() in classC.

Component

Firstly, let’s have a look at the Component source code.

...
/**
* Annotates an interface or abstract class for which a fully-formed, dependency-injected implementation is to be generated from a set of {
@linkplain #modules}.
....
@Retention(RUNTIME) // Allows runtimes to have specialized behavior interoperating with Dagger.
@Target(TYPE)
@Documented
public @interface Component {
....

So, this needs to be used on an interface/abstract class. The Scope that we discussed in our previous part, will be defined in this Component. So that the respective Activity,Fragment or Application using this respective component will get their set of Dependencies that are required by them in the respective scope that is defined in the Component.

This Component also provides the methods that need to be exposed so that the Dagger class generated for this Component can provide us with the respective dependencies

When a scope is declared in a Component, it may only contain un-scoped Bindings or bindings with that scope anywhere in the graph.

We will get to know the implementation of @Component in our example which we will be implementing in Part 4 and Part 5 of the series.

For now, understand that this interface/abstract class defines the connection between the provider of objects (modules) and the objects which express a dependency. The class for this connection is generated by the Dagger.

That’s it for this part of the series.

Please refer the Part 4 of the series here

Congratulations for getting introduced to the important annotations that are used in Dagger.

Thank you for your time.

Let’s connect on Twitter and LinkedIn

References:

--

--