web-dev-qa-db-ja.com

Dagger 2を使用したメソッド注入

Dagger 2を使用したメソッドインジェクションに関する適切な説明/例を見つけることができませんでした。

例:

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

_@Inject_でメソッドに注釈を付けた場合、メソッドシグネチャの引数にオブジェクトグラフから定義されたオブジェクトが挿入されると仮定するのは正しいですか?コードでこのメソッドを使用するにはどうすればよいですか?メソッド呼び出しを行うときに、すべての引数を提供することを期待しますが、これは目的を無効にします。

更新:

私が理解していることから、DinnerComponentが次のように設定されていると仮定すると、DinnerComponent.dinner()を呼び出すと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();
}
_

コンポーネント内でどの夕食がどれであるかを指定するにはどうすればよいですか?

33
Vas

あなたがそれを使用しているように見える方法と異なるメソッドインジェクションに関する1つの基本的な違いは、メソッドインジェクションはDaggerが依存関係を送信するための別の方法である DI-readyオブジェクトの注入、つまり、@ Inject-annotatedメソッドは、独自のコード内からではなく、構築時にDaggerによって1回呼び出されることを意味します。これにより、@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-annotatedコンストラクターまたは@Providesメソッドがない限り、コンポーネントから直接Chefを取得することはできませんが、couldコンポーネント上にvoidメソッドを作成します。このメソッドは、構築されたChefインスタンスを受け取り、フィールドとメソッドのインジェクションを使用して、必要な成分(または成分プロバイダー)をChefに提供します。 (詳細については @ Component および MembersInjector のドキュメントを参照してください。)

オブジェクトグラフでDinnerが利用できるように見えることはありません。 @Injectをコンストラクターに追加すると、そのコンストラクターを使用してオブジェクトグラフでオブジェクトを使用できることをDaggerに伝えますが、@ Injectをメソッドまたはフィールドに追加すると、Daggerに、注入プロセスの一部として、そのフィールドに値を入れるか、呼び出す必要があることを伝えるだけです指定された依存関係を持つメソッド。オブジェクトグラフでディナーを利用できるようにするには、ディナーコンストラクターに@ Inject-annotateアノテーションを付けるか、コンポーネントにフィードするモジュールに@Providesまたは@Bindsメソッドを配置する必要があります。

なぜこれを使用するのですか?オブジェクトがリフレクティブに作成される場合(例:Androidのアクティビティ、フラグメント、ビュー、または直列化可能オブジェクト)、@ Injectフィールドを公開しないことを検討します。そのような場合、フィールドでインジェクションを行うことにより、コンストラクターの制約を回避できます。同様に、私はこれを試していませんが、クラス階層を利用して@Injectでインターフェイスメソッドをマークし、DIコンテキストにいるかどうかにかかわらず、特定の依存関係をオブジェクトの一部としてオブジェクトに渡すことができます準備。

42
Jeff Bowman

メソッドに@Injectアノテーションを付けると、オブジェクトの作成直後、つまりコンストラクター呼び出しの直後にこのメソッドを実行するためのDagger命令が与えられます。これは、何かのために完全に構​​築されたオブジェクトが必要な場合に便利です。 この記事 にメソッドインジェクションの例があります。

このメソッドのパラメーターはDaggerによって提供されると言ってもいいでしょう。だからこそ、このメソッドを自分で呼び出すことになっていないのです。

12
Egor Neliuba