Why does Dagger 2 force me to use @Provides instead of @Binds

codejanovic :

I am looking into Dagger 2 (Java) right now and came across an issue right upon the start. Sadly, I was not able find a anything yet in the Dagger 2 Documentation or on Stackoverflow about it, so if you guys know some resources I would really appreciate it.

I prepared a minimal example within this repository here to explain whats my issue: https://github.com/stackoverflow-samples/dagger2-dependency-cycle

So we got an Application class that should be constructed

public class Application {

    @Inject
    public Application(SomeDependency one) {

    }

    public static void main(String[] args) {
        DaggerApplicationComponent.create().build();
    }
}

... with a dummy dependency

public class SomeDependency {

    @Inject
    public SomeDependency() {

    }
}

And of course the Dagger classes/interfaces ... .. a component interface:

@Component(modules = ApplicationModule.class)
public interface ApplicationComponent {
    Application build();
}

.. and a module:

@Module
abstract class ApplicationModule {
    @Provides
    static SomeDependency provideDepdendencyOne() {
        return new SomeDependency();
    }
}

What I dont get is why Dagger forces me to register SomeDepdendency with @Provides annotation and does not allow to register it via @Binds:

@Binds 
abstract SomeDependency bindDepdendencyOne(SomeDependency one);

Whenever I change the code from @Provides to @Binds it gives me the following errors:

[Dagger/DependencyCycle] Found a dependency cycle:
      io.github.codejanovic.dagger2.example.SomeDependency is injected at
          io.github.codejanovic.dagger2.example.ApplicationModule.bindDepdendencyOne(one)
      io.github.codejanovic.dagger2.example.SomeDependency is injected at
          io.github.codejanovic.dagger2.example.Application(one)
      io.github.codejanovic.dagger2.example.Application is provided at
          io.github.codejanovic.dagger2.example.ApplicationComponent.build()

Being unable to @Bind an implementation makes absolutely no sense to me. What do I oversee?

Thanks in advance.

David Medenjak :

You're wrong in assuming that you need @Binds or @Provides in the first place. You can and should be using constructor injection—not the pattern, but the Dagger generates the code for me kind.

You already have the constructor annotated with @Inject, thus Dagger knows about the class and how to create it. There's nothing else to do.

public class SomeDependency {

    @Inject
    public SomeDependency() {

    }
}

You don't need any @Provides, no @Binds, not even a @Module for this simple use case of yours. Your example should work right out of the box since both constructors are annotated with @Inject.

@Component
public interface ApplicationComponent {
    Application build();
}

If you need to specify a scope you can add it on the class.


@Provides should be used for code that you can't use constructor injection for, or that needs additional setup. Of course you can create all the objects manually (as you're doing in your example) but this has no real benefit and will just produce a lot of boilerplate that can be avoided.

@Binds is to be used with implementations that you need to bind to an interface. Optimally you'd use constructor injection for the implementation as well, but you can as well add it to the component builder (@BindsInstance) or create it in a @Provides annotated method.

@Binds MyInterface bindMyImplementation(MyImplementation implementation);

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=144813&siteId=1