I am not certain on the purpose for Dagger2's @Bind annotation.
From what i have read online im still not clear but here is an example:
@Module
public abstract class HomeModule {
@Binds
public abstract HomePresenter bindHomePresenter(HomePresenterImp
homePresenterImp);
}
and the class definitions look like this:
public interface HomePresenter {
Observable<List<User>> loadUsers();
}
public class HomePresenterImp implements HomePresenter {
public HomePresenterImp(){
}
@Override
public Observable<List<User>> loadUsers(){
//Return user list observable
}
}
why would i need to use @Binds if i can just use provides annotation as follows:
@Provides
public HomePresenter provideHomePresenter() {
return new HomePresenterImp();
}
what is the usecase for @Binds instead of @Provides ? if i use @Binds do i still need to declare it in my appcomponent (its an abstract class when i use @Binds)?
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.
With the @Inject annotation on the constructor, we instruct Dagger that an object of this class can be injected into other objects. Dagger automatically calls this constructor, if an instance of this class is requested.
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).
Modules are a way of telling Dagger how to provide dependencies from the dependency graph. These are typically high level dependencies that you aren't already contributing to the dependency graph through the @Inject constructor annotation we discussed in our previous article.
@Binds
can be perfectly equivalent to a @Provides
-annotated method like this:
@Provides
public HomePresenter provideHomePresenter() {
return new HomePresenterImp();
}
...though you'd probably prefer a variant that takes HomePresenterImp as a method parameter, which lets Dagger instantiate HomePresenterImp (assuming it has an @Inject constructor) including passing any dependencies it needs. You can also make this static
, so Dagger doesn't need to instantiate your Module instance to call it.
@Provides
public static HomePresenter provideHomePresenter(HomePresenterImp presenter) {
return presenter;
}
So why would you choose @Binds
instead? Dagger has a FAQ about it, but it boils down do these reasons:
static
will also accomplish this, but your @Provides method will still compile if you forget the static
. @Binds methods will not.Provider<HomePresenterImp>
to a Provider<HomePresenter>
and only keep one, rather than keeping one for HomePresenter that does nothing but call the one for HomePresenterImp.Thus, the entire thing would be well-represented as:
@Binds abstract HomePresenter bindHomePresenter(HomePresenterImp presenter);
Here a concrete case where you need Bind
annotation, imagine you got a BaseActivityModule
which is include in all your activity modules that provides your activity viewmodel.
@Module
object BaseActivityModule {
@Provides
@ActivityScope
@ActivityContext
@JvmStatic
fun provideViewModelProvider(
activity: AppCompatActivity,
viewModelFactory: ViewModelProvider.Factory
): ViewModelProvider = ViewModelProviders.of(activity, viewModelFactory)
}
Here you see we need to provide an AppCompatActivity
and a ViewModelProvider.Factory
. You cannot provide AppCompatActivity
with a Provide
annotation since activities are created by android.
We're assuming your concrete ActivityModule
for example MainActivityModule
will provide MainActivity
class either because you create a MainActivity sub component or you used ContributesAndroidInjector
to automatically create your sub components (but this is another talk).
So we have our MainActivityModule
providing MainActivity
and our MainActivityModule
includes our BaseActivityModule
which need an AppCompatActivity
. So here the Bind
magic, let's tell Dagger that when you need an AppCompatActivity
you can use our MainActivity
.
@Module(includes = [BaseActivityModule::class])
abstract class MainActivityModule {
@Binds
@ActivityScope
abstract fun bindActivity(activity: MainActivity): AppCompatActivity
}
You can see more from my project template here
Thanks to this source: https://www.valueof.io/blog/inject-provides-binds-dependencies-dagger-hilt
@Binds:
However, the advantage of using @Binds is that it reduces the amount of code generated (such as Module Factory classes). Less code to generate means the Kapt plugin has less work to do which can speed up build times in larger projects.
@Binds is a very specialized annotation though—it’s used to map an interface to an implementation. It can take only a single parameter and the type return is the interface implemented by the given parameter object.
If the implementation you are binding to takes constructor parameters, you can use a combination of @Inject and @Binds as shown in the example below:
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