Dependency Injection with Dagger2

This blog is in continuation of my previous article. In the previous article, we read about Architecture design patterns and differences between them. If you haven’t read it go through the link given below:

MVC vs MVP vs MVVM architecture in Android.

From the previous blog,

No Hard dependency: It should be fixed if every component should work on some limited amount of dependency. All dependencies should be provided from outside. Use Dependency Injections.

So, why to wait? Let's start.

What is a dependency on Android?

If one class uses an instance of another class then it is called dependency. For example- If X class holds the reference of Y class, then class X dependents on class Y. Thus we can say, class Y is the dependency of class X. So, the problem is, if we do changes in class one then we have to do the changes in another class also. So, to increase the rigidity, immorality, and fragility we use Dependency Injections. For example:

public class Stream {

    public static void main(String[] args) {
        Math math = new Math();
        Science science = new Science();
        Subject subject = new Subject(math, science);
        subject.read();
    }
    
}

In the above example, Math math = new Math(); and Science science = new Science(); shows the hard dependency. So, to avoid this we use dependency injection.

Dependency Injections:

Injection- Simply means passing these dependencies from the outside. It works on the principle of Inversion of Control (IoC)

Inversion of Control: It is generally meant any sort of programming which doesn't create the object. Instead, they get the objects which they need from outside sources. For example, let’s suppose you had a bakery and you hire someone from outside to bake cakes. This is the concept of IoC.

Dependency injection: DI facilitates a class to configure it’s dependency from outside not statically.

Advantages:

  • It helps to remove the boilerplate code. Because the initialization of dependencies handled by the injecting component.
  • Testing is easy.
  • Local Singletons (Scopes).

Some framework which uses DI is- Spring, Dagger, Android Annotation, RoboGuice, ButterKnife, etc.


Dagger:

Dagger is a framework that simply works on the Dependency Injection framework. We have to instruct dagger on, how to create them. This is achieved by using constructor injection, method injection and field injection.

Two versions of Dagger:

Dagger1- It was developed by Square. It’s now deprecated. Instances are generated at runtime using reflection.

Dagger2 - It is referred by Google there is a lot of improvement in performance, easier to debug and advance programming features. Instances are generated at compile time.

Let's see all these three one by one:

Injection/ Dependency Client:

A class that uses instance is the client or injection class. We have three places to put our injections with a symbol @Inject at constructor, methods, and fields.

A) Constructor Injection: We write @Inject on the top of the constructor. As shown in below example:

public class Subject 
{
    private Math math ;
    private Science science;

    @Inject
    public Subject(Math math, Science science ){}

    public void read(){ }
}

B.) Field Injection:- Field which participates in the injection is called field injection. Dagger doesn’t support Injection in private fields and the final field. Because the private field does not bind with our component and the final can’t change its value. As shown in the example:

public class Subject {
    @Inject 
    Math math ;

    private Science science ;   //can’t be injected

    @Inject
    public Subject(Science science ){}

    public void read(){ }
}

C.) Method Injection:- Method which participates in the injection is called Method injection. As shown in the example below:

public class Subject {
    Math math;
    private Science science;

    @Inject
    public Subject(Math math, Science science){}

    @Inject
    public void readMathBook(){ }

    public void read(){ }
}
Note: Dagger will first check the constructor, if not find, then go to Field and Method. If you want to inject field and method automatically then inject the constructor.

Modules and providers:

It is a creator. Its role is to provide instances. If we don’t own the class and it comes from outside then we use modules and providers. As it comes from the external class we can’t use @inject in it.

@Module- write on the top of the module class

@Module
class ScienceModule{

    @Provides
    ScienceBook provideScienceBooks(){
        return new ScienceBook();
    }
}

Static method and field: You should use a static keyword for fields and methods if there is no dependency on instance state of any module. It improves performance. If all methods are static in module class, then make the class abstract.
The example is given below:-

@Module
abstract class ScienceModule
{
    @Provides
    static ScienceBook provideScienceBooks()
    {
        return new ScienceBook();
    }
}

Then it won’t instantiate and directly call in the class.

Components in Dagger:

Components are dagger access points. We can say, it is a dependency manager or an interface that binds the module and injects the class. It holds all the dependency together. The dagger has a component and its sub-components.

It is denoted by @Component.
@Component tells us what all modules need to provide or an array of modules to a component. It takes a particular class context in which data has to bind.


@Component(modules={ApplicationModule.class,  ActivityModule.class})


But if we have to share our data between modules, then we can write-

@Component(dependencies={ApplicationModule.class,  ActivityModule.class})


Example using the module in our component:

@Component(modules={ApplicationModule.class,  ScienceModule.class})
public interface SubjectComponent{
    
    Subject getSubject();
    
    void inject(SubjectActivity activity); // this line is to inject the class.
}

How to call dagger component:

public class SubjectActivity extends AppCompatActivity {
    @Inject
    Subject subject;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_subject);

        //Calling dagger component
        DaggerSubjectComponent component = DaggerSubjectComponent.create();
        component.inject(this);
        subject.read();
    }
}

Here is the link for Github repo of Dagger 2 implementation.

This was the basic info about what is dependency injection and how it works with Dagger 2. In the next blog, we will read about Sub-Component, Qualifiers, Scopes, and Binds vs Provides, etc.