【问题标题】:Method injection using Dagger 2使用 Dagger 2 进行方法注入
【发布时间】:2016-09-05 23:50:33
【问题描述】:

我还没有找到关于使用 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();
}

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

【问题讨论】:

  • 我不知道你是从哪里得到这个例子的,但是看着它我想你可能想阅读关于辅助注射的文章。
  • 你可以使用@Named注解。
  • 不需要空的ctor public DinnerModule() {}

标签: java android dependency-injection dagger-2


【解决方案1】:

与您使用它的方式相比,Dagger 方法注入的一个根本区别是,在构造或注入 DI-ready 对象时,Dagger 方法注入是just another way for Dagger to send in dependencies,这意味着 em>@Inject-annotated 方法意味着 Dagger 在构造时调用一次,而不是在您自己的代码中调用。这使得您不太可能 @Inject-annotate makeDinnerfryDinner 或任何其他具有有意义的副作用或返回值的方法。相反,将方法注入视为构造函数式注入的构造后机会。

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

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 图中的参数调用它。

无论是否使用 Dagger 可构造 Chef,这都适用:除非您有 @Inject-annotated 构造函数或 @Provides 方法,否则您将无法直接从组件中获取 Chef,但您可以 在接收已构建的Chef 实例的组件上创建一个void 方法。该组件方法将使用字段和方法注入来为厨师提供他们可能需要的成分、提供者、选项或惰性。有关详细信息,请参阅 @ComponentMembersInjector 文档。

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

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

【讨论】:

  • 在多次阅读这个答案并亲自尝试之后,我想我终于可以加快方法注入的速度了。谢谢!
  • Provider -> 什么是Provider?
  • @MarianPaździoch 从概念上讲,它是一个可以创建新 T 实例的工厂,通常通过调用 T get()。 Dagger 和 Guice 和 Spring 一样,使用标准接口javax.inject.Provider<T>
【解决方案2】:

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

你说得对,这个方法的参数将由 Dagger 提供,所以你不应该自己调用这个方法。

【讨论】:

  • “在构造函数调用之后”这不是真的,在 \@Inject ctor 和 \@Inject 字段初始化之后
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-07
  • 1970-01-01
  • 2016-08-31
  • 2022-09-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多