Dagger 2 - 两个提供相同接口的方法

假设我有:

public interface Shape  {}


public class Rectangle implements Shape {

}

public class Circle implements Shape {

}

我有一个 ApplicationModule,它需要为 RecCircle 提供实例:

@Module
public class ApplicationModule {
    private Shape rec;
    private Shape circle;

    public ApplicationModule() {
        rec = new Rectangle();
        circle= new Circle ();
    }

    @Provides
    public Shape provideRectangle() {
        return rec ;
    }

    @Provides
    public Shape provideCircle() {
        return circle;
    }
}

应用程序组件

@Component(modules = ApplicationModule.class)
public interface ApplicationComponent {
    Shape provideRectangle();
}

使用代码的方式 - 它不会编译。错误说

错误:(33, 20) 错误:形状被绑定多次。

对我来说,这是不可能的,因为组件正在尝试查找一个实例,并且它找到了其中两个实例,因此它不知道要返回哪一个实例。Shape

我的问题是 - 我该如何处理这个问题?


答案 1

我最近在这篇文章中发布了这样一个问题的答案:

Dagger 2 :获取具有@Named的同一对象的多个实例时出错

您需要在模块中使用如下:@Named("someName")

@Module
public class ApplicationModule {
private Shape rec;
private Shape circle;

public ApplicationModule() {
    rec = new Rectangle();
    circle= new Circle ();
}

@Provides
 @Named("rect")
public Shape provideRectangle() {
    return rec ;
}

@Provides
 @Named("circle")
public Shape provideCircle() {
    return circle;
}

}

然后,无论您需要注入它们在哪里,只需编写

@Inject
@Named("rect")
 Shape objRect;

它很有趣,但你必须在Kotlin中以不同的方式注入:

@field:[Inject Named("rect")]
lateinit var objRect: Shape

答案 2

@Qualifier注释是区分具有相同类型的不同实例或注入请求的正确方法。主用户指南页面有一整节关于它们

@Qualifier @Retention(RUNTIME)
public interface Parallelogram {} /* name is up to you */

// In your Module:
@Provides @Parallelogram
public Shape provideRectangle() {
    return rec ;
}

// In your other injected types:
@Inject @Parallelogram Shape parallelogramShape;
// or
@Inject @Parallelogram Provider<Shape> parallelogramShapeProvider;

// In your Component:
@Parallelogram Shape provideRectangle();

题外话:虽然我同意你不应该在注入类型中使用sector11,但如果需要,模块是完全正确的调用位置。除了添加限定符注释之外,我会说你的模块对我来说看起来正好。newnew


自定义限定符注释相比,编辑有关使用@Named:

  • @Named是一个内置注释,就像我上面创建的注释一样。对于简单的情况,它的工作原理很好,但是由于绑定只是一个字符串,因此在检测有效密钥或自动完成密钥时,您将无法从IDE获得太多帮助。@Qualifier
  • 与 Named 的字符串参数一样,自定义限定符可以具有字符串、基元、枚举或类文本属性。对于枚举,IDE 通常可以自动完成有效值。
  • @Named自定义限定符可以通过在组件方法上指定注释,以完全相同的方式从注释访问,就像我上面所做的那样。@Parallelogram

推荐