How to implement dependency injection using Dagger2 in Android

Step 0 :  Ask yourself 3 questions

  1. Which object do you want dagger to provide?
  2. Where do you want dagger to provide this object?
  3. How will you construct or provide this object?
Let's say we want SharedPreferences to be supplied to us by Dagger
  1. Which object do you want dagger to provide?
    Shared Preferences, create a module that returns a SharedPreferences object
  2. Where do you want dagger to provide this object?
    In 2 places, Fragment A and Fragment B in this app, use the @Inject annotation at both places and create a component that has 2 methods, where the first method takes a reference to Fragment A and the second method takes a reference to Fragment B so that Dagger can generate an implementation that extends your Component interface and use your module to construct the SharedPreferences object wherever required and supply it.
  3. How will you construct or provide this object?
    Create a method inside your module with a @Provides annotation that returns an object of the type you want dagger to provide, in our case, that type is SharedPreferences.


Step 1: Construct a module that knows how to create the objects ( SharedPreferences  in this case) which will be used by Dagger.

Since we need a context which should be Application Context as SharedPreferences tend to be used everywhere, make a constructor that accepts an object of your custom Application class. Notice the @Singleton annotation which indicates that only a single object of SharedPreferences will be supplied to everyone once its created.


Step 2: Create a component interface called StorageComponent that has all the methods which simply specify where to inject the reference.

 Dagger 2 will generate the concrete implementation for your interface and fill the necessary code using your module that you created earlier in Step 1. Notice that we plan to use @Inject annotations inside Fragment A and Fragment B and therefore we have 2 methods inside our Component interface that exactly tell Dagger the list of all places where we need a SharedPreferences object. Also notice the modules annotation that tells Dagger to use our module declared in the earlier step to actually construct a SharedPreferences object when needed.


Step 3 : Adding the @Inject annotations 


We add the @Inject annotations inside Fragment A and Fragment B where we want Dagger to supply us with a SharedPreferences object. Build the program at this point so that Dagger can generate an implementation for your component interface. We use this implementation in the next step.

Step 4 : Implement Builder

In this step, Dagger has compiled our modules and components and generated an implementation of our component interface. Its name is DaggerStorageComponent in our case. Call its builder() method, supply an object of our StorageModule and finally call its build() method.

Step 5: Passing Reference

 Notice how we have passed a reference of Fragment A by getting our Activity, get our Application from our Activity, typecast it to our custom Application, get the component from that and simply call inject() method which was actually a part of our Component interface declared in Step 2. This is how the whole process works




@Singleton
@Component(modules = StorageModule.class)
public interface StorageComponent {
void inject(FragmentA fragmentA);
void inject(FragmentB fragmentB);
}
view raw component1.java hosted with ❤ by GitHub
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
((MyApplication)getActivity().getApplication()).getComponent().inject(this);
}
view raw fragment1.java hosted with ❤ by GitHub
@Inject
SharedPreferences mPreferences;
view raw inject.java hosted with ❤ by GitHub
@Module
public class StorageModule {
private final MyApplication application;
public StorageModule(MyApplication application){
this.application = application;
}
@Singleton
@Provides
SharedPreferences provideSharedPreferences(){
return PreferenceManager.getDefaultSharedPreferences(application);
}
}
view raw module1.java hosted with ❤ by GitHub
public class MyApplication extends Application {
StorageComponent component;
@Override
public void onCreate() {
super.onCreate();
component = DaggerStorageComponent
.builder()
.storageModule(new StorageModule(this))
.build();
}
public StorageComponent getComponent() {
return component;
}
}

Comments