首页 > 解决方案 > 如何在进行构造函数注入时向构造函数提供参数?

问题描述

我正在使用 dagger2 框架进行依赖注入。

如何使用构造函数注入创建依赖对象 B(和 INJECT)的实例。B类有一个参数构造函数。请在下面找到示例。

//This is class A, which is dependent on Class B.
//This has to create instance of B, with a (int) parameter.
class A {
    @Inject
    public B objectB;

    public A(int some_value){
        //This one I want to make it through dagger2
        //objectB = new B(some_value);

        BComponent bComponent = DaggerBComponent.builder().build();
        bComponent.provideB(this);
    }
}

//This is Class B, which has constructor injection.
//Constructor has a int parameter. 
class B {

    @Inject
    public B(int var){
        other_method(var);
    }
}

//This is dagger module, which provides Object B
@Module
public class BProvider {

    @Provides
    public B getB() {
        return new B();
    }
}

//This is dagger component, provide class-B dependency to class-A 
@Component(modules = {BProvider.class})
public interface BComponent {
    void provideB(A objA);
}

标签: androiddependency-injectiondagger-2

解决方案


从评论中的阐述:

我正在尝试构造函数注入来实现依赖。ClassA 依赖于 ClassB。ClassB 有参数构造函数,比如 ClassB(int param)。这个参数是在运行时提供的,所以我的困惑是 dagger 是如何创建对象 B 的。

如果 B 的参数每次都相同,则在您的对象图中

如果您的参数是键、ID 或其他配置设置,则可能会出现这种情况。如果是这样,您可以使用@ProvidesModule 中的方法来教 Dagger 在您请求时如何提供 ClassB 对象。

@Module
public abstract class YourModule {
  @Provides static ClassB provideClassB() {
    return new ClassB(/* your constant here */);
  }
}

因为@Provides方法可以采用来自对象图的参数,所以您甚至可以从其他地方获取您的值:

@Module
public abstract class YourModule {
  @Provides static ClassB provideClassB(SomeDependendency someDep) {
    return new ClassB(someDep.getParameterForClassB());
  }
}

如果 B 只接受自定义参数

如果您的 ClassB 是数据对象或一次性对象,则可能会出现这种情况,特别是如果您不需要替换 ClassB 进行测试。(不要模拟数据对象。如果所有这些都是真的,那么 ClassB 不需要成为对象图的一部分。直接调用构造函数。

ClassB myB = new ClassB(someParameter);

有时这种区别被称为injectables 与 newables:如果您有需要相互访问的复杂且相互关联的类,则您有一个injectable,并且应该在外部提供对它的引用。如果你有一个不需要替换的紧密包含的类,你就有一个newable,并且可以直接调用构造函数或静态工厂方法。

如果 B 有注入参数和构造函数参数

在某些情况下,像 ClassB 这样的类同时需要一次性构造函数参数从图中注入的参数。尽管这可能是一个微妙的暗示,表明该类做得太多,但有一些常见的解决方法将这两个输入组合到同一个构造函数参数列表中。这称为辅助注入,允许在 DI 框架提供工厂的地方创建工厂对象,您可以使用它来获得所需的值。

/* in ClassB */ public ClassB(DepA a, DepB b, int param) { /* ... */ }

/* ClassBFactory */
public ClassBFactory {
  Provider<DepA> depAProvider;
  Provider<DepB> depBProvider;
  public ClassBFactory(
      Provider<DepA> depAProvider,
      Provider<DepB> depBProvider) {
    /* set depAProvider and depBProvider */
  }

  public ClassB get(int param) {
    return new ClassB(depAProvider.get(), depBProvider.get(), param);
  }
}

因为这类似于 Dagger 的样板生成,但在其他依赖注入框架中更可重用,Dagger建议Google 项目AutoFactory基于检查依赖项和类来生成该实现。您需要向 ClassB 添加一些注释才能使其正常工作,但它可以让您区分图形提供的 deps 和一次性的 deps,并且如果您的 dep 列表发生更改,您就不必更改构造函数调用。


推荐阅读