Dependency Injection with Dagger

Read Time 2 minutes

According to Single Responsibility principle, no class of your application should create new instances of other classes it needs. These objects Dependencies should be created and provided by someone else.

Dagger is a dependency injection framework for android being used widely. Today I’ll shortly explain the different components of dagger and how we can set up and use dagger for our android applications.

First of all, we need to add these dependencies to  dependencies section of  app build.gradle file:

apt 'com.google.dagger:dagger-compiler:2.0.2'
provided 'javax.annotation:javax.annotation-api:1.2-b01'

We also need to apply apt plugin in our app build.gradle file:

apply plugin: ‘com.neenbedankt.android-apt’

and finally add apt plugin class path to our project’s build.gradle file dependencies section:

classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'

Now we are all set to use dagger in our application.

There are three main things in Dagger.

1- Module    A place where all the dependencies need to be injected are defined.

2- Component  A place where we define where these dependencies are going to be used(injected).

3- Injections   Where we actually inject dependencies (Activities, fragments etc) using @inject notation. There are two types of injections:

  • Field Injection
  • Constructor Injection

 

So lets say we have an simple android application for your login, which contains only one screen. Which has two input fields for username and password and a login button for login.

Lets list down our dependencies

  • Retrofit REST API interface (Since I am going to use Retrofit for REST api calls).
  • A Repository which actually calls the Retrofit API for Login.
  • A Login UseCase  (Since I will be using Clean Architecture for this sample).

Lets define our application level dependencies:

@Module
public class ApplicationModule {

    @Singleton
    @Provides
    public Repository provideRepository(RepositoryImpl repository) {
        return repository;
    }

    @Singleton
    @Provides
    public OkHttpClient provideOkHttpClient() {

        final HttpLoggingInterceptor.Level LOG_LEVEL = HttpLoggingInterceptor.Level.BODY;

        HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
        loggingInterceptor.setLevel(LOG_LEVEL);

        return new OkHttpClient.Builder().addInterceptor(loggingInterceptor).build();


    }

    @Singleton
    @Provides
    public SampleAPI provideNuKashAPI(OkHttpClient okHttpClient) {


        final String BASE_URL = "http://sample-server.com/";

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .client(okHttpClient)
                .build();


        return retrofit.create(SampleAPI.class);

    }
}

Modules are defined with @Module annotation. @Provides specifies the this function is providing this dependency, while @Singleton is scope annotation. @Singleton is the highest scope. Other scopes can be defined and used.

Let’s define the Component for this module:

@Singleton
@Component(modules = ApplicationModule.class)
public interface ApplicationComponent {

    void inject(MainActivity mainActivity);

   //expose to sub-graphs
    Repository provideRepository();

}

Again @Component annotation is used to define components. We are specifying which modules will provide dependencies for this component on the top.  We are defining that this component is going to be injected in MainActivity.

Now, let’s say we have only MainActivity (no fragment 🙂 where we want to call this SampleAPI. 

private ApplicationComponent appComponent;
@Inject  SampleAPI sampleAPI;
 
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    injectDependencies();
    
}

private void injectDependencies(){
  
   this.appComponent = DaggerApplicationComponent.builder()
        .applicationComponent(appComponent)
        .build();
   this.appComponent.inject(this);

}

public onLogin(){
    
    String usrname=....;
    String password=...; 
    //call sampleAPI to call the Rest api
   
    sampleAPI.login(username,password);
}

DaggerApplicationComponent is the generated class by Dagger for our ApplicationComponent. We use this for all the injections.

So dagger will inject sampleAPI in our MainActivity and we can simple use it!.

 

 

 

 

 

 

Leave a Comment

Your email address will not be published. Required fields are marked *