Dagger: Bind interface to implementation without boilerplate

Created on 7 Apr 2016  路  9Comments  路  Source: google/dagger

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?

feature request

Most helpful comment

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;
}

All 9 comments

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!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

sagarwaghmare07 picture sagarwaghmare07  路  3Comments

Axrorxoja picture Axrorxoja  路  3Comments

blackberry2016 picture blackberry2016  路  3Comments

rciovati picture rciovati  路  3Comments

JakeWharton picture JakeWharton  路  3Comments