Here in this tutorial i will explain you what the dependency injection is and why do we need it? I will also let you know why do we use it and what happens when we don’t use it?We will also learn about how we inject dependency in our android project using dagger2 .
What is Dependency Injection?
The term “Dependency Injection” or in short “DI” is a design pattern ,which is build upon the concept of Inversion of Control.
- That means a class should get its dependencies from outside.
- In more simpler words, we can say class cannot instantiate another class using a new keyword inside it. Instead, you have to supply the object from outside.
To understand it in more detail, let’s break the term Dependency Injection in two parts Dependency and Injection.
Get GITHUB code from Here.
What is Dependency?
Consider the following Java class.
public class Customer {
Private Account account;
public Customer()
{
account = new Account();
}
}
In the above class, we are creating the object of class Account inside the class Customer. So here, we can say that the Customer is dependent on Account object or we can say Account is a dependency for the class Customer.
What is Injection?
As we seen the Customer is Dependent on Account, now how do we get this Account object inside the Customer class .
We can consider the following ways.
- Create Account object inside the Customer Constructor or inside the Customer class.
public class Customer
{
Private Account account;
public Customer()
{
account = new Account();
}
}
Or
public class Customer
{
Private Account account;
account = new Account();
}
But this is a bad idea because now Customer class get dependent on Account object .
Ideally java class should be as independent from other classes, this increases the possibility of —–
- reusing these classes.
- Testing these classes independently from other classes.
- Instead of using new to instantiate the Account inside Customer’s constructor we can pass the Account as an argument to the Customer’s constructor.
public class Customer {
private Account account;
public Customer(Account account)
{
this.account = account;
}
}
Doing this makes the class Customer now independent from class Account .So this is what we call as Dependency Injection. Means supplying the dependencies(object) from outside the class instead of creating the object inside the class using new keyword.
What is Dagger 2?
Dagger is a fully static, compile-time dependency injection framework for both Java and Android. It is an adaptation of an earlier version created by Square and now maintained by Google.
Understanding Basics of Dagger2
Before moving ahead in our Android Project, let’s understand first the basics of Dagger 2.
So we have three major things in Dagger.
Dependency Provider
- Dependencies are the objects that we need to instantiate inside a class. And we learned before that we cannot instantiate a class inside a class. Instead, we need to supply it from outside. So the class which will provide us the objects that are called dependencies is called Dependency Provider.
- And in dagger2 the class that you want to make a Dependency Provider, you need to annotate it with the @Module annotation.
- And inside the class, you will create methods that will provide the objects (or dependencies). With dagger2 we need to annotate these methods with the @Provides annotation.
- @Module and @Provides: define classes and methods which provide dependencies
Dependency Consumer
- dependency consumer is a class where we need to instantiate the objects. But now we don’t need to instantiate it with the new keyword (I am assuming java here). We do not even need to get it as an argument. But dagger will provide the dependency, and for this, we just need to annotate the object declaration with @Inject.
Component
- Finally, we need some connection between our dependency provider and dependency consumer.
For this, we will create an interface by annotating it with @Component. And rest of the thing will be done by Dagger.
Using Dagger2 in android project
In this tutorial my aim is to understand you, how to use Dagger2 in our project instead of working with retrofit .Android retrofit Example is my previous post Which i am going to modify here so that i can focus on dagger2.You can get source code of Android retrofit Example from here.
- Firstly go to build.gradle(app level) and add the dependency for dagger2 as shown below and sync the project.
//dagger2
compile 'com.google.dagger:dagger:2.13'
annotationProcessor 'com.google.dagger:dagger-compiler:2.13'
Creating Modules
For this project, we need two modules. The first one is the AppModule, and the Next one is ApiClientModule.
App Module
This module will provide the Context. You already know that we need Context everywhere, and in Retrofit as well we need the context object. And as the DI rule says we need an outsider to supply the objects, so here we will create this module that will give us the Context.
- Create a new class named AppModule and write the following code.
AppModule.java
package com.c1ctech.androiddagger2example.module;
import android.app.Application;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
@Module
public class AppModule {
private Application mApplication;
public AppModule(Application mApplication) {
this.mApplication = mApplication;
}
@Provides
@Singleton
Application getApplication() {
return mApplication;
}
}
- The above code is straightforward, and we just use a new annotation @Singleton. In dagger, we have this annotation, when we want a Single object.
ApiClient Module
This module will provide us retrofit object which we will use later in our MainActivity to make request.
- So, create the class named AppClientModule and write the following code.
ApiClientModule.java
package com.c1ctech.androiddagger2example.module;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
@Module
public class ApiClientModule {
public final String BASE_URL;
public ApiClientModule(String url) {
this.BASE_URL = url;
}
@Provides
@Singleton
Retrofit getClient() {
return new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
}
We have done with the Modules. Now let’s define the Component and then we will inject the objects.
Building Component
- Now, we will create the Component.
ApiComponent.java
package com.c1ctech.androiddagger2example;
import com.c1ctech.androiddagger2example.module.ApiClientModule;
import com.c1ctech.androiddagger2example.module.AppModule;
import javax.inject.Singleton;
import dagger.Component;
@Singleton
@Component(modules = {ApiClientModule.class, AppModule.class})
public interface ApiComponent {
void inject(MainActivity mainActivity);
}
- Now create a class named MyApplication. In this class we will build the ApiComponent.
MyApplication.java
package com.c1ctech.androiddagger2example;
import android.app.Application;
import com.c1ctech.androiddagger2example.module.ApiClientModule;
import com.c1ctech.androiddagger2example.module.AppModule;
public class MyApplication extends Application {
private ApiComponent mApiComponent;
@Override
public void onCreate() {
super.onCreate();
mApiComponent = DaggerApiComponent.builder()
.appModule(new AppModule(this))
.apiClientModule(new ApiClientModule("http://cricapi.com/"))
.build();
}
public ApiComponent getComponent() {
return mApiComponent;
}
}
Before moving ahead Rebuild your project.
- So, we have our API component, but we need to instantiate this class when our application launches. And for this, we need to define it inside our App Manifest file. So open your AndroidManifest.xml and modify it as shown below.
Injecting Dependency with Dagger 2
Now finally, we can inject the dependency.
- Come inside MainActivity.java and modify it as below.
Mainactivity.Java
package com.c1ctech.androiddagger2example;
import android.app.Application;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import com.c1ctech.androiddagger2example.adapter.MatchCalenderAdapter;
import com.c1ctech.androiddagger2example.model.CalenderResponse;
import com.c1ctech.androiddagger2example.model.MatchCalender;
import java.util.List;
import javax.inject.Inject;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
public class MainActivity extends AppCompatActivity {
//injecting retrofit and application dependency
@Inject
Retrofit retrofit;
@Inject
Application application;
private final static String API_KEY = "ENTER YOUR API KEY";
private static final String TAG = MainActivity.class.getSimpleName();
RecyclerView recyclerView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
((MyApplication) getApplication()).getComponent().inject(this);
recyclerView = (RecyclerView) findViewById(R.id.match_calender_recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.addItemDecoration(new DividerItemDecoration(this, LinearLayoutManager.VERTICAL));
//Using retrofit
ApiInterface apiService = retrofit.create(ApiInterface.class);
Call<CalenderResponse> call = apiService.getMatchCalender(API_KEY);
call.enqueue(new Callback<CalenderResponse>() {
@Override
public void onResponse(Call<CalenderResponse> call, Response<CalenderResponse> response) {
int statuscode = response.code();
List<MatchCalender> matchlist = response.body().getData();
//Using application
recyclerView.setAdapter(new MatchCalenderAdapter(matchlist, application));
}
@Override
public void onFailure(Call<CalenderResponse> call, Throwable t) {
Log.e(TAG, t.toString());
}
});
}
}
Writing the below line allow the MainActivity to inject or use any of the dependencies of all the modules defined in ApiComponent.
((MyApplication) getApplication()).getComponent().inject(this);
When you run your application it will look like this:
It will show the list of matches that will be occur today or later.
I hope that this tutorial will help you in understanding the dagger2.Thank you.
Great post.
I have read almost dozen of blog and article to get more insight of dagger 2 before giving it a try in my real project but the way you explained is as simple than anyone can get it easily.Thanks for writing such a great post. I will wait for other coming blog on dagger.
Thank you 🙂