Ofe*_*mon 31 java android dependency-injection dagger dagger-2
让我说我有:
public interface Shape {}
public class Rectangle implements Shape {
}
public class Circle implements Shape {
}
Run Code Online (Sandbox Code Playgroud)
我有一个ApplicationModule,它需要为Rec和Circle提供实例:
@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;
}
}
Run Code Online (Sandbox Code Playgroud)
和ApplicationComponent:
@Component(modules = ApplicationModule.class)
public interface ApplicationComponent {
Shape provideRectangle();
}
Run Code Online (Sandbox Code Playgroud)
使用代码的方式 - 它将无法编译.错误说
错误:(33,20)错误:形状被多次绑定.
对我来说这是不可能的,因为组件正在尝试查找Shape实例,并且它找到了其中的两个,因此它不知道返回哪一个.
我的问题是 - 我该如何处理这个问题?
Ami*_*ati 43
我最近在这篇文章中发布了这样一个问题的答案:
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;
}
Run Code Online (Sandbox Code Playgroud)
}
然后,无论你需要注入它们,只需写
@Inject
@Named("rect")
Shape objRect;
Run Code Online (Sandbox Code Playgroud)
Jef*_*ica 13
@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();
Run Code Online (Sandbox Code Playgroud)
除此之外:虽然我同意您不应该new在注入类型中使用sector11,但new如果需要,模块就是正确的调用位置.除了添加限定符注释之外,我会说你的模块看起来恰到好处.
关于使用@Named与自定义限定符注释相比的编辑:
@Qualifier注释,就像我上面创建的那样.对于简单的情况,它工作得很好,但由于绑定只是一个字符串,因此您无法从IDE中获得有关检测有效密钥或自动完成密钥的帮助.@Named通过在组件方法上指定注释,可以通过注释以完全相同的方式访问自定义限定符,@Parallelogram如上所述.我不认为new在构造函数中使用运算符是个好主意Module.这将在初始化对象图形时(即,当您调用时new ApplicationModule())创建每个提供的对象的实例,而不是在Dagger第一次需要对象时.在这种情况下(只有两个对象),它可以忽略不计,但在较大的项目中,这可能会导致应用程序启动时出现瓶颈.相反,我会遵循@ sector11的建议,并在带@Provides注释的方法中实例化您的对象.
至于提供两个相同类型的对象,@ Jeff和@Amir都是正确的.您可以使用提供的@Named()限定符,也可以创建自己的限定符,如下所示:
@Qualifier @Retention(RetentionPolicy.RUNTIME)
public @interface RectangleShape {}
@Qualifier @Retention(RetentionPolicy.RUNTIME)
public @interface CircleShape {}
Run Code Online (Sandbox Code Playgroud)
然后你ApplicationModule应该看起来像这样:
@Module
public class ApplicationModule {
@Provides @RectangleShape // @Named("rectangle")
public Shape provideRectangle() {
return new Rectangle();
}
@Provides @CircleShape // @Named("circle")
public Shape provideCircle() {
return new Circle();
}
}
Run Code Online (Sandbox Code Playgroud)
有了这个,您可以将这些对象注入到您的类中,如下所示:
@Inject @RectangleShape /* @Named("rectangle") */ public Shape mRectangle;
@Inject @CircleShape /* @Named("circle") */ public Shape mCircle;
Run Code Online (Sandbox Code Playgroud)
如果您需要在Shape没有@Inject注释的情况下提供类的实例,则可以在您的Component课程中执行此操作:
@Component(modules = { ApplicationModule.class })
public interface ApplicationComponent {
void inject(MyApplication application);
@RectangleShape // @Named("rectangle")
Shape getRectangle();
@CircleShape // @Named("circle")
Shape getCircle();
}
Run Code Online (Sandbox Code Playgroud)
这些方法将提供由带@Provides注释的方法提供的每个类的相同实例.
| 归档时间: |
|
| 查看次数: |
14649 次 |
| 最近记录: |