Dagger 2 Annotations: @Binds & @ContributesAndroidInjector
This article is a part of the “Dagger and the Dahaka” series. In this article we will briefly look at two annotations : @Binds
and @ContributesAndroidInjector
. It is not mandatory to have read the previous articles to understand this, but a basic understanding of Dagger is a must.
Dagger has many helpful Annotations which can not only reduce the code you write, but also make your generated code much more optimized and one of those annotations is @Binds
.
Binds
This annotation provides a replacement of @Provides
methods which simply return the injected parameter. Let’s take an example,
We have a LoginPresenter
which implements LoginContract.Presenter
. Without @Binds
, the provider method for it will be something as follows :
@Provides
public LoginContract.Presenter
provideLoginPresenter(LoginPresenter loginPresenter) {
return loginPresenter;
}
In the above case, we can instead use @Binds
annotation and make the above method abstract
:
@Binds
public abstract LoginContract.Presenter
provideLoginPresenter(LoginPresenter loginPresenter);
Of course, we will also need to mark our Module as abstract in this case, which is more efficient than a concrete one and thus makes @Binds
more efficient.
What makes our abstract Module more performant?
@Provides
methods are instance methods and they need an instance of our module in order to be invoked. If our Module is abstract and contains @Binds
methods, dagger will not instantiate our module and instead directly use the Provider
of our injected parameter (LoginPresenter
in the above case).
What if your module contains both @Provides
and @Binds
methods?
Dagger documentation has great FAQ questions on @Binds
vs @Provides
methods. In case, your Module has both @Provides
and @Binds
methods, you have two options :
- Simplest would be to mark your
@Provides
instance methods as static. - If it is necessary to keep them as instance methods, then you can split your module into two and extract out all the
@Binds
methods into an abstract Module.
To know about more such optimizations and even others which the recent version 2.12
of dagger has brought along with it. I recommend watching “Optimizing Dagger on Android” by Ron Shapiro, Google.
@ContributesAndroidInjector
If you have seen a basic implementation of dagger-android
, you would know that it introduces some amount of boilerplate code. When you are trying to switch to dagger-android or converting your current app to use it. The most cumbersome I think is having to create separate sub-components for each of your Activities, Fragments, Services, etc. and adding those to the injectorFactories
of your DispatchingAndroidInjector
(by using @IntoSet
)
Dagger Android introduced an annotation which can reduce the Component
Binds
IntoSet
Subcomponent
ActivityKey
FragmentKey
etc. boilerplate for you.
If you have a simple module like the following, you can then let dagger handle the rest.
@Module
public abstract class LoginModule {
@Binds
public abstract LoginContract.Presenter
provideLoginPresenter(LoginPresenter loginPresenter);
}
All you need to do is write the following snippet inside the Module
of the component, which is going to be the super-component of the generated LoginComponent
. Example, If you have an AppComponent
and you want dagger to generate a LoginSubcomponent
for your LoginActivity
, you will write the following snippet inside your AppModule
.
@ContributesAndroidInjector(modules = LoginModule.class)
abstract LoginActivity loginActivity();
It’s a good practice to extract out a separate ActivityBindingModule
for all such bindings and include it in the modules
list of your AppComponent
as follows :
@Singleton
@Component(modules = {
AppModule.class,
ActivityBindingModule.class})
public interface AppComponent
Now, let’s refer to the documentation of @ContributesAndroidInjector
and figure out what’s going on here :
- “Generates an AndroidInjector for the return type of this method” : It will generate
AndroidInjector<LoginActivity>
. (More about it in upcoming posts) - “This annotation must be applied to an abstract method in a Module that returns a concrete Android framework type.” i.e. Activity / Fragment, etc.
Following is the boilerplate that gets generated for you when you use @ContributesAndroidInjector
:
//Simplified Generated File@Module(subcomponents =
Module_LoginActivity.LoginActivitySubcomponent.class)
public abstract class Module_LoginActivity {
private Module_LoginActivity() {}
@Binds
@IntoMap
@ActivityKey(LoginActivity.class)
abstract AndroidInjector.Factory<? extends Activity>
bindAndroidInjectorFactory(
LoginActivitySubcomponent.Builder builder);
@Subcomponent(modules = LoginModule.class)
public interface LoginActivitySubcomponent extends
AndroidInjector<LoginActivity> {
@Subcomponent.Builder
abstract class Builder extends
AndroidInjector.Builder<LoginActivity> {}
}
}
- It generates the
LoginActivitySubcomponent
. - It adds the necessary
@Subcomponent
annotation for us. - It adds an entry of (
LoginActivity.class
,LoginActivitySubcomponent.Builder
) to the Map of Injector Factories used byDispatchingAndroidInjector
. Dagger-Android uses this entry to build ourLoginActivitySubcomponent
and perform injections forLoginActivity
. - Also, binds
LoginActivity
to the object-graph. (See the source code ofAndroidInjector
to know how, Hint :@BindsInstance
)
Similarly, you can also use @ContributesAndroidInjector
with any of the android framework types like Fragments, Services, etc. Here’s an example using Fragments.
Scoping with @ContributesAndroidInjector
If you want to scope dependencies inside of your LoginModule
, then you need your generated LoginActivitySubcomponent
to be scoped as well. Learn more about scopes here. To do this, you can specify a scope along with your @ContributesAndroidInjector
annotation and that will let you scope anything inside your LoginModule
as follows.
@ContributesAndroidInjector(modules = LoginModule.class)
@ActivityScope
abstract LoginActivity loginActivity();
This will generate your LoginActivitySubcomponent
annotated with an ActivityScope
.
//Simplified Generated File@Module(subcomponents =
Module_LoginActivity.LoginActivitySubcomponent.class)
public abstract class Module_LoginActivity {
...
@Subcomponent(modules = LoginModule.class)
@ActivityScope
public interface LoginActivitySubcomponent extends
AndroidInjector<LoginActivity> {
@Subcomponent.Builder
abstract class Builder extends
AndroidInjector.Builder<LoginActivity> {}
}
}
Now that the Component is scoped, you can apply the general rules of scoping and mark any of your @Binds
methods with @ActivityScope
:
@Binds
@ActivityScope
public abstract LoginContract.Presenter provideLoginPresenter(LoginPresenter loginPresenter);
That’s it :)
As you can see in the above case, by understanding what’s going on under the hood we are trying to befriend the beast of generated code (Dahaka) which in-turn helps us optimize our generated code and reduce boilerplate.
In the upcoming articles we will try to learn more about dagger-android
and what goes on behind the scenes. If you would like to see an implementation of dagger-android
you can have a look the the Dahaka github repository here.

So just Befriend the Beast and use Dagger-Android.
Special Thanks to Mike Nakhimovich for reviewing 🙂 and suggesting the edits.
I am myself an Android Developer getting chased by “Dahaka” every day. While going through this series of blog posts if you think that something can be done in a better way, Kindly share it so that we can all befriend the beast together.

Stay tuned for the whole series 🙂