Last month, I went into detail about how to use the recently released Dagger 2 Android modules, and how you can make your injection code much more concise.

Google have gone through a lot of effort to enable developers to use Dagger with very little integration and more importantly on how to use a common injection paradigm without the injection target being concerned with how it is being provided with it’s necessary dependencies.

The fundamental actor in this scenario is the AndroidInjector class which can target different elements of an Android application such as Activities, Fragments, and Services.

Additionally, Google introduced a new annotation ContributesAndroidInjector to generate the necessary components used for Android injection, giving us a clear example on how to use them, but most importantly allowed us to use safe paradigms without having to write extensive boilerplate code.

Here’s an example of how you can use the annotation to set-up your activities injection:

public interface ActivityBindingModule {
  @ContributesAndroidInjector(modules = AwesomeModule.class)
  AwesomeActivity awesomeActivity();
}

This will generate a Component and a DispatchingAndroidInjector to handle injection for this activity, with AwesomeActivity only having to call AndroidInjection.inject(this) or extend from DaggerAppCompatActivity.

Notice here how AwesomeModule is an interface here? Because it only has abstract methods it doesn’t need to be defined as a class, which is awesome!

Something else you might have noticed here, is that you are no longer responsible for creating the component, and by extension, it’s modules.

This is important, firstly since we are no longer responsible for writing this code, we are forced into using the correct, safe behaviour; but potentially problematically we are no longer able to provide the module with parameters.

Normally, you would be included to build the component inside the activity, being able to instantiate a module with any parameters you would want to be included for use inside the dependency graph like so:

public class AwesomeActivity extends AppCompatActivity {
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ((AwesomeApplication) getApplication())
    .getApplicationComponent()
    .awesomeActivityComponentBuilder()
    .awesomeModule(new AwesomeModule(getIntent().getStringExtra("extra.awesome.id")))
    .build()
    .injectMembers(this);
  }
}

Urgh… See how ugly this code looks? and how the activity not only makes direct reference to the application, but creates it’s own dependency graph builder!

So, we’ve already covered that we can drop this ugly code, but how do we get the necessary parameters from the intent for example into our module?

Quite simply!

Consider that the string being provided here is a dependency of the module itself, would it not make sense to use our handy dependency injection framework for this? Dagger works best when it’s allowed to handle most if not all of your dependencies.

class AwesomeActivity extends DaggerAppCompatActivity {
  @Qualifier
  @Documented
  @Retention(RUNTIME)
  @interface AwesomeId {
  }
  @AwesomeId
  String getAwesomeId() {
    return getIntent().getStringExtra("extra.awesome.id");
  }
  @Module
  abstract class AwesomeModule {
    @Provides
    @AwesomeActivity.AwesomeId
    static String awesomeId(AwesomeActivity activity) {
      return activity.getAwesomeId();
    }
  }
}

We can expose the necessary parameter through the activity to the module when Dagger creates its dependency graph, and how do we get the activity? When Dagger generates the module implementations it binds the instance of the Activity to the module, meaning that your activity is already part of the dependency graph, and since the component is garbage collected after injection, there is no chance of it leaking context.

You don’t have to use a qualifier annotation here, but I’d recommend doing so since it clearly identifies itself apart from a simpler Named annotation, or no annotation at all.

tl;dr

  • Dagger generated injectors already have an activity provision
  • It’s safer to use these as the component is disposed after injection