Avoid Dagger injection half done

If you have ever made some sizable App, you probably have used Dagger 2. An excellent Dependency Injection Library especially for Android. I’m not going into detail of how to do it here, as there are lots of tutorial out there about it.

Obviously, to setup Dagger 2, you’ll setup the appropriate modules, component and instantiate your component in your application (most commonly done in application).

An example of of the way it instantiated as below (extracted and slightly simplified from this tutorial)

public class MyApp extends Application {

private MyComponent myComponent;

@Override
public void onCreate() {
super.onCreate();

myComponent = DaggerMyComponent.builder()
.appModule(new AppModule(this))
.netModule(new NetModule("https://api.github.com"))
.build();

}

public MyComponent getMyComponent() {
return myComponent;
}
}

It seems all okay, and fully done once you have Component and Modules setup accordingly. You could get your class members instantiated magically, once you have your class object injected into the Dagger Component.

What am I trying to show?

Well, the above thought it’s all done, but it’s not fulfilling the spirit of dependency injection in full. The catch is per the bold phrase below

You could get your class members instantiated magically, once you have your class object injected into the Dagger Component.

You need to inject your class object into the component before you could get your class members magically instantiated.

Therefore, for any object that have injected class members, it first need to have access to the Dagger Component.

So how would you access the Dagger Component, as per the above example?You’ll need have access to MyApp object, and then call getMyComponent().

For some object like Activity or Fragment, this would be easy.

  • For Activity → ((MyApp)getApplication()).getMyComponent()
  • For Fragment → ((MyApp)(getActivity().getApplication())).getMyComponent()

Even for some cases, if we have access to the Context, we could get the base context to access it.

But what if the class object down the chain that has no access to these? You’ll have to pass the context or application in, even if it is deep within the chain of classes. So that defeats the purpose of dagger injection. This I call Half Done, given that we have to pass something along the way before inject into the component.

How to solve this?

Back to some basic concept. Singleton pattern could be applied. Below is a simple modification to meet the need. It’s not fully Singleton as it doesn’t control the instantiation of myComponent, but it gets the jobs done.

public class MyApp extends Application {

private static MyComponent myComponent;

@Override
public void onCreate() {
super.onCreate();

myComponent = DaggerMyComponent.builder()
.appModule(new AppModule(this))
.netModule(new NetModule("https://api.github.com"))
.build();

}

public static MyComponent getMyComponent() {
return myComponent;
}
}

So to access myComponent, the call is as simple as making the below call anywhere, to inject your class object; then all your class members would be magically injected. No need to pass your application or context around just for this purpose.

MyApp.getMyComponent().inject(this)