Because @Binds methods are just a method declaration, they are expressed as abstract methods — no implementation is ever created and nothing is ever invoked. On the other hand, a @Provides method does have an implementation and will be invoked.
@Binds prevents Dagger from having to codegen and keep a separate Factory/Provider for the object, since Java doesn't give Dagger access to know that the implementation is as simple as it is.
Annotation Type ContributesAndroidInjectorThe injector is implemented with a Subcomponent and will be a child of the Module 's component. This annotation must be applied to an abstract method in a Module that returns a concrete Android framework type (e.g. FooActivity , BarFragment , MyService , etc).
@Binds
and @ContributesAndroidInjector
methods must be abstract, because they don't have method bodies. That means that they must go on an interface or abstract class. @Provides
methods may be static
, which means they can go on abstract classes and Java-8-compiled interfaces, but non-static ("instance") @Provides
methods don't work on abstract classes. This is explicitly listed in the Dagger FAQ, under the sections "Why can’t @Binds
and instance @Provides
methods go in the same module?" and "What do I do instead?".
If your @Provides
method doesn't use instance state, you can mark it static
, and it can go onto an abstract class adjacent to your @Binds
methods. If not, consider putting the bindings like @Binds
and @ContributesAndroidInjector
into a separate class--possibly a static nested class--and including that using the includes
attribute on Dagger's @Module
annotation.
A little addition to Jeff's solution above:
you may create inner interface instead of static inner class, like this:
@Module(includes = AppModule.BindsModule.class)
public class AppModule {
// usual non-static @Provides
@Provides
@Singleton
Checkout provideCheckout(Billing billing, Products products) {
return Checkout.forApplication(billing, products);
}
// interface with @Binds
@Module
public interface BindsModule {
@Binds
ISettings bindSettings(Settings settings);
}
}
If you are in kotlin world, another alternative is to leverage companion object
@Module
abstract class MyDaggerModule {
@Binds
abstract fun provideSomething(somethingImpl: SomethingImpl): Something
companion object {
@Provides
fun provideAnotherThing(): AnotherThing {
return AnotherThing()
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With