Java 带Dagger的嵌套/递归注入

Java 带Dagger的嵌套/递归注入,java,android,dagger,Java,Android,Dagger,当使用Dagger时,什么样的方法允许在同样通过注入实例化的对象上自由/轻松地实例化@Inject字段 例如,下面的代码将向给定的Foo对象中注入一个Bar类型的对象。它将以显示的两种方式之一执行此操作。但是,每个条形图对象的Sly字段与该行为不匹配 福 砰 狡猾的 模块 测验 在这两种情况下,Bar的Sly都没有被实例化/@注入。当然,Dagger允许构造函数注入,这就解决了问题。我想知道是否有其他方法可以将这些类塞进构造函数的参数列表中。什么对您有效?所以这里的问题是,Bar上有@Injec

当使用Dagger时,什么样的方法允许在同样通过注入实例化的对象上自由/轻松地实例化@Inject字段

例如,下面的代码将向给定的Foo对象中注入一个Bar类型的对象。它将以显示的两种方式之一执行此操作。但是,每个条形图对象的Sly字段与该行为不匹配

狡猾的

模块

测验


在这两种情况下,Bar的Sly都没有被实例化/@注入。当然,Dagger允许构造函数注入,这就解决了问题。我想知道是否有其他方法可以将这些类塞进构造函数的参数列表中。什么对您有效?

所以这里的问题是,Bar上有@InjectSly,但是您在@Provides方法中提供了Bar@提供方法覆盖默认实例化行为,因此您告诉Dagger实例化“new Bar()”,并将其作为Bar规定的实现返回

最简单的方法就是删除provideBar()方法,因为它是不必要的。如果具体类型具有@Inject构造函数或@Inject字段,Dagger将注入其依赖项并创建它,除非它具有不可访问的构造函数或没有@Inject的参数化构造函数。但是您上面的类Bar{}完全适合于隐式绑定,而不使用@Provides方法

如果出于某种原因需要更改默认行为,您仍然可以在@Provides方法中创建它,但必须手动传入注入值@但是,提供方法本身可以通过向@Provides方法本身添加参数来注入。所以你可以这样做

@Provides
Bar provideBar(Sly sly) {
  Bar bar = new Bar();
  bar.sly = sly;
  return bar;
}
@Provides方法承担正确设置实例的所有责任,包括更新、分配、任何初始化逻辑等

但是,根据上面的示例,简单的解决方案是从模块中删除provideBar(),并让Dagger自动初始化Bar

对于嵌套注入,Dagger 2似乎有一些不同的选择:请求一个组件、MembersInjector,或者给Bar一个@Inject注释的构造函数

如果Bar具有@Inject注释的构造函数,则可以实现完全不变性:

class Bar {
  private final Sly sly;

  @Inject
  public Bar(Sly sly) {
    this.sly = sly;
  }
}
当您仅部分注入成员时,另一种选择是使用@Provides方法和MembersInjector或component(MembersTestComponent?)作为方法参数:

@Provides
Bar provideBar(MembersInjector<Bar> injector) {
  Bar bar = new Bar();
  injector.inject(bar);
  return bar;
}
@提供
棒供应器B(部件喷油器喷油器){
条形=新条形();
注入器。注入器(巴);
返回杆;
}
不幸的是,提供MembersTestComponent参数会将模块耦合回您的组件,从而降低解决方案的内聚性。如果Bar包含组件提供的范围值(例如,Jake Wharton的Devxx 2014演讲中的用户内部Tweeter),则提供MembersInjector特别有用

@Module(
    injects = {
        Foo.class,
        Bar.class
    }
)
public class ExampleTestModule {
  @Provides
  Bar provideBar() {
    return new Bar();
  }

  @Provides
  Sly provideSly() {
    return new Sly();
  }
}
public void testWorksWithInject() {
  Foo foo = new Foo();
  ObjectGraph.create(new ExampleTestModule()).inject(foo);
  assertEquals("...", foo.getValue()); // NullPointerException
}

public void testWorksWithGet() {
  Foo foo = ObjectGraph.create(new ExampleTestModule()).get(Foo.class);
  assertEquals("...", foo.getValue()); // NullPointerException
}
@Provides
Bar provideBar(Sly sly) {
  Bar bar = new Bar();
  bar.sly = sly;
  return bar;
}
class Bar {
  private final Sly sly;

  @Inject
  public Bar(Sly sly) {
    this.sly = sly;
  }
}
@Provides
Bar provideBar(MembersInjector<Bar> injector) {
  Bar bar = new Bar();
  injector.inject(bar);
  return bar;
}