使用Dagger 2进行方法注射 [英] Method injection using Dagger 2

查看:96
本文介绍了使用Dagger 2进行方法注射的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I haven't managed to find a good explanation/example on method injection using Dagger 2. Could someone please help me understand?

示例:

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

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

So if I annotate my method with @Inject, am I correct to assume that the arguments in the method signature will be injected with defined objects from the object graph? How can I use this method in my code then? It will still expect me to supply all the arguments, when I make the method call, which sort of defeats the purpose.

更新:

所以根据我的理解,如果我调用 DinnerComponent.dinner(),那么Dinner对象将可用,假设我的DinnerComponent设置如下:

So from what I understand the Dinner object will be available if I call DinnerComponent.dinner(), assuming my DinnerComponent is set up like this:

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

我的DinnerModule设置如下:

and my DinnerModule is set up like this:

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

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

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

如果我想要吃晚餐怎么办?
所以我们来介绍一下这个方法:

What happens if I want my dinner fried? So let's introduce this method:

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

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

How can I specify within the component which dinner is which?

推荐答案

方法注入的一个根本区别在于你似乎使用它的方式是 方法注入只是Dagger发送依赖关系的另一种方式就绪对象,这意味着 @Inject-annotated方法应由Dagger在构造时调用一次,而不是在您自己的代码中调用。这使你不太可能 @Inject -annotate makeDinner fryDinner ,或任何其他具有有意义的副作用或返回值的方法。相反,将方法注入视为构造函数式注入的事后机会。

One fundamental difference about method injection that differs from the way you seem to be using it is that method injection is just another way for Dagger to send in dependencies when constructing or injecting a DI-ready object, which means that @Inject-annotated methods are meant to be called by Dagger once on construction and not from within your own code. This makes it very very unlikely that you would @Inject-annotate makeDinner, fryDinner, or any other method that has meaningful side effects or return values. Instead, treat method injection as a post-facto opportunity for constructor-style injection.

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

在这种情况下,当您向厨师请求注射时,Dagger会看到@Inject-annotated方法并调用它。除非您有@Inject-annotated构造函数或@Provides方法,否则您将无法直接从您的Component获取Chef,但您可以创建 void Chef 实例的Component上的code>方法,该实例使用字段和方法注入为Chef提供他们可能需要的成分(或成分提供者) 。 (参见 @Component MembersInjector 文档了解详情。)

In this case, when you request injection on a Chef, Dagger will see the @Inject-annotated method and call it. Unless you have an @Inject-annotated constructor or @Provides method, you won't be able to get a Chef directly from your Component, but you could create a void method on the Component which receives a constructed Chef instance and which uses field and method injection to provide that Chef with the ingredients (or ingredient Providers) they may need. (See the @Component and MembersInjector docs for details.)

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

Note that in no case does Dinner appear available on the object graph! Adding @Inject to a constructor tells Dagger that it can use that constructor to make the object available on the object graph, but adding @Inject to a method or field merely tells Dagger that as part of the injection process it should populate that field or call that method with the given dependencies. If you want to make a Dinner available on the object graph, you'll need to @Inject-annotate the Dinner constructor, or put a @Provides or @Binds method on a Module that you feed into the Component.

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

Why would you use this? Consider a case where objects are created reflectively (e.g. Activities, Fragments, and Views in Android, or Serializable objects), where you would prefer not to expose @Inject fields. In those cases, you could work around constructor constraints by having your injection happen on a field. Similarly, though I haven't tried this, you could take advantage of class hierarchy to mark an interface method with @Inject, ensuring that whether or not you're in a DI context you can pass certain dependencies to an object as part of their preparation.

这篇关于使用Dagger 2进行方法注射的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆