使用 Dagger 2 的方法注入 [英] Method injection using Dagger 2

查看:38
本文介绍了使用 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 注释我的方法,我是否正确地假设方法签名中的参数将使用对象图中的已定义对象注入?那么如何在我的代码中使用这种方法呢?当我进行方法调用时,它仍然希望我提供所有参数,这有点违背了目的.

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 方法注入的一个根本区别在于,Dagger 方法注入是 Dagger 在构造或注入时发送依赖项的另一种方式一个 DI-ready 对象,这意味着 @Inject-annotated 方法应该在构造时被 Dagger 调用一次,而不是从你自己的代码中调用.这使得您不太可能@Inject-注释makeDinnerfryDinner 或任何其他具有有意义的副作用或返回值的方法.相反,将方法注入视为构造器样式注入的构建后机会.

One fundamental difference about Dagger method injection, compared to the way you are using it, is that Dagger 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-construction opportunity for constructor-style injection.

(当然,你总是可以在方法级别练习一般的依赖注入,将你的依赖传递到一个方法调用中,这样方法本身就不必创建它们.然而,这不是 Dagger 定义的意思方法注入,它无助于支持这种情况.)

(Of course, you can always practice general dependency injection at the method level, passing your dependencies into a method call so that the method itself does not have to create them. However, this is not what Dagger means with its definition of method injection, and it does not help support that case.)

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 方法并使用 Dagger 图中的参数调用它.

In this case, when you request injection on a Chef instance, Dagger will see the @Inject-annotated method and call it with arguments from the Dagger graph.

无论是否有 Chef 是 Dagger-constructable 都可以工作:除非您有 @Inject-annotated 构造函数或 @Provides 方法,否则您将无法直接从您的组件中获取 Chef,但您可以 在 Component 上创建一个 void 方法,该方法接收一个已经构建的 Chef 实例.该 Component 方法将使用字段和方法注入来为 Chef 提供他们可能需要的成分、提供者、可选项或惰性.请参阅 @Component 和 <有关详细信息,请参阅 href="http://google.github.io/dagger/api/2.0/dagger/MembersInjector.html" rel="nofollow noreferrer">MembersInjector 文档.

This works with or without Chef being Dagger-constructable: 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 an already-constructed Chef instance. That Component method would use field and method injection to provide that Chef with the ingredients, Providers, Optionals, or Lazys they may need. See the @Component and MembersInjector docs for details.

请注意,Dinner 在任何情况下都不会出现在对象图上!将@Inject 添加到方法或字段只是告诉 Dagger 作为注入过程的一部分,它应该填充该字段或使用给定的依赖项调用该方法.如果您想让 Dinner 在对象图上可用,您需要对 Dinner 构造函数进行 @Inject-annotate,或者将 @Provides 或 @Binds 方法放在您提供给组件的模块上.

Note that in no case does Dinner appear available on the object graph! 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.

为什么要使用方法注入?尽管构造函数注入更可取,并且允许类的字段为 final,但请考虑以反射方式创建对象的情况(例如 Android 中的活动、片段和视图,或可序列化对象).字段注入(其中 Dagger 填充 @Inject 注释的字段)也可以工作,但在某些情况下,您可能不想公开 @Inject 注释的字段.在这些情况下,您可以通过在 @Inject 注释的方法上进行注入来解决构造函数约束.类似地,虽然我还没有尝试过,但您可以利用类层次结构来标记带有 @Inject 的接口方法:这将确保无论您是否处于 DI 上下文中,您都可以将某些依赖项作为一部分传递给对象他们的准备.

Why would you use method injection? Though constructor injection is preferable, and allows the class's fields to be final, consider a case where objects are created reflectively (e.g. Activities, Fragments, and Views in Android, or Serializable objects). Field injection (where Dagger populates an @Inject-annotated field) would work as well, but in some cases you may prefer not to expose @Inject-annotated fields. In those cases, you could work around constructor constraints by having your injection happen on an @Inject-annotated method. Similarly, though I haven't tried this, you could take advantage of class hierarchy to mark an interface method with @Inject: this would ensure 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天全站免登陆