Sometimes, for architectural reasons, I have interfaces with only one concrete class implementing them. Writing @Provides methods for these cases can involve a lot of boilerplate, especially if the constructor has a lot of dependencies.
e.g.
@Provides
@ActivityScope
public FavouritesListContract.Presenter provideFavouritesListPresenter(FavouritesClient favouritesClient,
SearchStorage searchStorage, SettingsStorage settingsStorage, GoogleAnalyticsHelper googleAnalyticsHelper) {
return new FavouritesListPresenter(favouritesClient, searchStorage, settingsStorage, googleAnalyticsHelper);
}
As long as the concrete implementation has an @Inject constructor it ought to be possible to just bind the class to the interface.
My thinking is that the binding still belongs in a Module. Perhaps a list of bindings could be provided in the @Module annotation?
Yes, we are working on a feature that will let you do exactly that.
In the meantime, if FavouritesListPresenter has an @Inject constructor, this formulation is equivalent and _much_ more brief:
@Provides
@ActivityScope
public FavouritesListContract.Presenter provideFavouritesListPresenter(FavouritesListPresenter impl) {
return impl;
}
Ah, sneaky! It hadn't occurred to me to try that. 馃榾
@gk5885 has an inject constructor (meaning that all params are provided in modules) or actually has the @Inject annotation applied on it?
@vanniktech It needs the @Inject annotation. It's using the normal dependency resolution/injection process, but with the addition of the @Provides method to actually associate the interface and class.
See Pump and Thermosiphon in the docs
Dagger 2.4 has been released, check out @Binds!
@ronshapiro Could dagger detect @Inject constructor of interface implementation class automatically, and reduce the @Binds annotated method?
Unfortunately not, since multiple classes might be implement the same interface on the same classpath, but should not be doubly bound in the same component. Consider this:
interface Base {}
class BaseTwo implements Base {
@Inject BaseTwo() {}
}
class BaseTen implements Base {
@Inject BaseTen() {}
}
Which Base would you expect to get?
Similarly, consider on Android:
class MainActivity implements View.OnClickListener {
@Inject MainActivity() {}
@Override
public void onClick(View v) { ... }
}
class DetailsActivity implements View.OnClickListener {
@Inject DetailsActivity() {}
@Override
public void onClick(View v) { ... }
}
That would generate duplicate bindings for View.OnClickListener, which you probably don't want bound at all.
Got it! Thanks!
Most helpful comment
Yes, we are working on a feature that will let you do exactly that.
In the meantime, if
FavouritesListPresenterhas an@Injectconstructor, this formulation is equivalent and _much_ more brief: