使用Dagger 2进行方法注入

时间:2016-09-05 23:50:34

标签: java android dependency-injection dagger-2

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

示例:

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

因此,如果我用@Inject注释我的方法,我是否正确假设方法签名中的参数将从对象图中注入定义的对象?我如何在我的代码中使用此方法呢?当我进行方法调用时,它仍然期望我提供所有参数,这会破坏目的。

更新

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

@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();
}

如何在组件中指定哪个晚餐是哪个?

2 个答案:

答案 0 :(得分:42)

与您使用它的方式不同的方法注入的一个基本区别是 method injection is just another way for Dagger to send in dependencies在构造或注入DI就绪对象时,这意味着 @Inject-annotated方法是由Dagger在构造时调用的,而不是在您自己的代码中调用。这使得@Inject - 注释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-annotated构造函数或@Provides方法,否则您将无法直接从Component获取Chef,但可以在Component上创建void方法它接收一个构造的Chef实例,并使用字段和方法注入为Chef提供他们可能需要的成分(或成分提供者)。 (有关详细信息,请参阅@ComponentMembersInjector文档。)

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

你为什么要用这个?考虑一种反射创建对象的情况(例如Android中的Activities,Fragments和Views,或Serializable对象),您不希望公开@Inject字段。在这些情况下,您可以通过在字段上进行注入来解决构造函数约束。类似地,虽然我没有尝试过这个,你可以利用类层次结构来标记一个带@Inject的接口方法,确保你是否在DI上下文中,你可以将某些依赖项传递给一个对象作为他们的一部分。制备

答案 1 :(得分:9)

使用@Inject注释方法,Dagger指令在对象创建后立即执行此方法 - 在构造函数调用之后。当您需要完全构造的对象时,这非常有用。在this article中有一个方法注入的例子。

你是对的,说这个方法的参数将由Dagger提供,这就是为什么你不应该自己调用这个方法。