为什么Dagger 2强迫我使用@Provides而不是@Binds

时间:2019-02-15 16:24:26

标签: java dagger-2

我现在正在研究Dagger 2(Java),并从一开始就遇到了一个问题。遗憾的是,我在Dagger 2文档中或Stackoverflow上都找不到任何相关内容,因此,如果你们知道一些资源,我将非常感谢。

我在此存储库中准备了一个最小的示例,以说明我的问题:https://github.com/stackoverflow-samples/dagger2-dependency-cycle

所以我们得到了一个应该构造的 Application

public class Application {

    @Inject
    public Application(SomeDependency one) {

    }

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

...具有虚拟依赖项

public class SomeDependency {

    @Inject
    public SomeDependency() {

    }
}

当然还有Dagger类/接口... ..组件界面:

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

..和一个模块:

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

我无法理解的是为什么Dagger强迫我使用SomeDepdendency注释注册@Provides并不允许通过@Binds对其进行注册:

@Binds 
abstract SomeDependency bindDepdendencyOne(SomeDependency one);

每当我将代码从@Provides更改为@Binds时,就会出现以下错误:

[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()

无法@Bind实现对我来说绝对没有意义。我要监督什么?

谢谢。

2 个答案:

答案 0 :(得分:1)

假设首先需要@Binds@Provides是错误的。您可以并且应该使用构造函数注入-不是模式,而是 Dagger为我生成代码

您已经用@Inject注释了构造函数,因此Dagger知道有关该类以及如何创建它的信息。没什么可做的。

public class SomeDependency {

    @Inject
    public SomeDependency() {

    }
}

对于您的这种简单用例,您不需要任何@Provides@Binds,甚至不需要@Module。您的示例应该可以立即使用,因为两个构造函数都用@Inject进行了注释。

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

如果需要指定范围,可以将其添加到类中。


@Provides应该用于不能使用构造函数注入的代码,或者需要其他设置的代码。当然,您可以手动创建所有对象(如您在示例中所做的那样),但这并没有真正的好处,只会产生很多可以避免的样板。

@Binds将与您需要绑定到接口的实现一起使用。最佳情况下,您也可以将构造函数注入用于实现,但是也可以将其添加到组件生成器(@BindsInstance)中,或通过带有注释的方法@Provides创建。

@Binds MyInterface bindMyImplementation(MyImplementation implementation);

答案 1 :(得分:1)

如果您的班级被标记为@Inject构造函数:

public class SomeDependency {

    @Inject // <----
    public SomeDependency() {

    }
}

然后,仅当您需要将其“绑定”作为接口的实现或至少不同于其具体类型的类型时,才需要@Binds(或@Provides)。

此外,如果您的对象具有@Inject构造函数,则您无需在模块中实例化它,因为Dagger已经知道如何实例化它。

因此,要修复代码,您需要做的只是:

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

已解决。