使用Dagger 2进行方法注入


问题内容

在使用Dagger 2进行方法注入方面,我还没有找到很好的解释/示例。有人可以帮我理解吗?

例:

@Inject
public Dinner makeDinner(Pasta pasta, Sauce sauce) {
    mPan.add(pasta);
    mPan.add(sauce);
    return mPan.cookDinner();
}

因此,如果用注释我的方法@Inject,是否可以正确地假定方法签名中的参数将注入对象图中定义的对象?那我该如何在代码中使用这种方法呢?当我进行方法调用时,仍然希望我提供所有参数,这将达到目的。

更新:

因此,据我了解DinnerComponent.dinner(),假设我的DinnerComponent的设置如下,则如果我调用,Dinner对象将可用:

@Component(modules = DinnerModule.class)
public interface DinnerComponent {
    Dinner dinner();
}

我的DinnerModule设置如下:

@Module
public class DinnerModule {
    public DinnerModule() {}

    @Provides
    Pasta providePasta() { return new Pasta(); }

    @Provides
    Sauce provideSauce() { return new Sauce(); }
}

如果我要炸晚餐怎么办?因此,让我们介绍一下这种方法:

@Inject
public Dinner makeDinner(Pasta pasta, Sauce sauce) {
    mPan.add(pasta);
    mPan.add(sauce);
    return mPan.fryDinner();
}

我如何在组件中指定哪一顿晚餐?


问题答案:

方法注入的一个根本区别与您似乎使用的方法不同,它是
方法注入只是Dagger
在构造或注入DI就绪对象时发送依赖项的另一种方法
,这意味着 @Inject注释的方法是意味着Dagger在构建时会被调用,而不是在您自己的代码中调用
。这使得@Inject-annotate
makeDinnerfryDinner或任何其他具有有意义的副作用或返回值的方法的可能性非常小。相反,将方法注入视为构造函数式注入的事后机会。

public class Chef {
  private Provider<Pasta> mPastaProvider;
  private Sauce mSauce;

  @Inject
  public void registerIngredients(     // can be named anything
      Provider<Pasta> pastaProvider,
      Sauce sauce) {                   // T and Provider<T> both work, of course
    mPastaProvider = pastaProvider;
    mSauce = sauce;
  }

  /* Non-@Inject */ public Dinner cookDinner() {
    mPan.add(mPastaProvider.get());
    mPan.add(mSauce);
    return mPan.cookDinner();
  }

  /* Non-@Inject */ public Dinner fryDinner() {
    mPan.add(mPastaProvider.get());
    mPan.add(mSauce);
    return mPan.fryDinner();
  }
}

在这种情况下,当您请求在Chef上进行注入时,Dagger将看到@ Inject-
annotated方法并对其进行调用。除非您具有@Inject注释的构造函数或@Provides方法,否则您将无法直接从Component获取Chef,但是
可以void在Component上创建一个方法,该方法接收构造的Chef实例并使用字段和方法注入为厨师提供他们可能需要的食材(或食材供应商)。(有关详细信息,请参见@ComponentMembersInjector文档。)

请注意,在任何情况下Dinner对象图都不会显示!在构造函数中添加@Inject告诉Dagger它可以使用该构造函数使对象在对象图上可用,但是在方法或字段中添加@Inject只是告诉Dagger作为注入过程的一部分,它应该填充该字段或调用具有给定依赖性的该方法。如果要在对象图上提供Dinner,则需要@
Inject-Annotation Dinner构造函数,或将@Provides或@Binds方法放在要馈入组件的模块上。

你为什么要用这个?考虑一种情况,其中对象是以反射方式创建的(例如,Android中的“活动”,“片段”和“视图”,或“可序列化的”对象),而您不希望公开@Inject字段。在这些情况下,可以通过在字段上进行注入来解决构造函数约束。同样,尽管我没有尝试过,但是您可以利用类层次结构来使用@Inject标记接口方法,以确保无论您是否在DI上下文中,都可以将某些依赖项作为对象的一部分传递给对象制备。