Dagger 2: ユーザーが入力したパラメータをオブジェクトに挿入する 質問する

Dagger 2: ユーザーが入力したパラメータをオブジェクトに挿入する 質問する

授業があるとしようユーティリティオブジェクト(クラスのインスタンス)を受け取るバリデーター

Util 内で Validator クラスのインスタンス化を避けたいので、コンストラクター経由で渡します。

public class Util {

   @Inject
   public Util(Validator validator) {

   }


}

Validator インスタンスを提供するモジュールがあります:

@Provides
@Singleton
Validator provideValidator() {
    return Validator.getInstance();
}

Util クラスのインスタンス:

@Provides
Util provideUtil(Validator validator) {
    return new Util(validator);
}

Util のインスタンスを生成するコンポーネントを接続しました。

Util getUtil()

私のアクティビティ内では、次のように呼び出すことができます。

Util myUtil = getComponent.getUtil();

これらはすべて正常に動作します。インスタンス化されると、myUtil には Validator クラスの適切なインスタンスが含まれます。

ここで、String変数を渡します。住所(UI 経由のユーザー入力)。コンストラクターを変更して、Validator のインスタンスとユーザーが入力した文字列の両方を渡すようにします。

@Inject
public Util(Validator validator, String address) {

}

2 番目のパラメータを渡す方法がまったくわかりません。誰か教えてくれませんか?

理想的には、Util を次のようにインスタンス化します。

Util myUtil = getComponent.getUtil(txtAddress.getText());

ベストアンサー1

数週間前に Dagger 2 を調べ始めたとき、私もあなたと同じ疑問を抱いていました。この問題 (および他のほとんどの Dagger 2 関連の問題) に関する情報はなかなか見つからないので、これがお役に立てば幸いです。

最も基本的な答えは、それはできないということです。あなたが探しているのは、補助注射であり、Dagger 2の一部ではありません。他の依存性注入(DI)フレームワーク、例えばギースはこの機能を提供しているので、調べてみてください。もちろん、Dagger 2 を使用してやりたいことを実現する方法はまだあります。

工場 工場 工場

DI と組み合わせて実行したいことを実行する標準的な方法は、ファクトリ パターンを使用することです。基本的には、address提供されるオブジェクト作成メソッドへの引数などの実行時パラメータを受け取る、注入可能なファクトリ クラスを作成します。

あなたの場合、インスタンス化時にUtilFactoryDagger 2 が を注入し、のインスタンスを作成するValidatorメソッドを提供する が必要になります。は、 の注入されたインスタンスへの参照を保持して、メソッドでのインスタンスを作成するために必要なものがすべて揃うようにする必要があります。create(String address)UtilUtilFactoryValidatorUtilcreate

このようなファクトリーのコードを書くのは面倒です。オートファクトリー、これにより負担がいくらか軽減されます。Guice の支援インジェクションは、Dagger 2 + AutoFactory と非常によく似た動作をするようです (ただし、より優れた構文糖衣が使用されています)。

その他のモジュール/コンポーネント

この場合、あなたがそうしたいとは思わないが、できたアドレスを提供するモジュールを作成するだけです (そして新しいコンポーネントをインスタンス化します)。すべての可能なアドレスに対して新しい @Module クラスを作成する必要はありません。代わりに、アドレスをモジュールのコンストラクタに引数として渡すことができます。teano が提案したように、@BindsInstance アノテーションを使用して同様の結果を得ることができます。

これがアンチパターンかどうかはわかりません。私にとっては、これは場合によっては許容できる方法のように思えますが、それは実際に「多くの」オブジェクトの初期化に同じアドレスを使用している場合のみです。新しいコンポーネントをインスタンス化することは絶対に望ましくありません。そして注入を必要とするオブジェクトごとに新しいモデルを作成します。これは効率的ではなく、注意しないと、Dagger を使用しない場合よりも定型コードが多くなってしまいます。

DI を(常に)使用しない: インジェクタブルとニューアブル

DIフレームワークについて学ぶ際に私にとって非常に役立ったのは、DIフレームワークを使用するとない初期化するにはDIを実行する必要があることを意味します全てオブジェクトの。経験則として、コンパイル時にわかっていて、他のオブジェクトと静的な関係があるオブジェクトを注入します。実行時の情報は注入しないでください。

私は思うこれこのテーマに関する良い投稿です。「newables」と「injectables」の概念を紹介しています。

  • 注射剤DI グラフのルートに近いクラスです。これらのクラスのインスタンスは、DI フレームワークが提供および注入することが期待される種類のオブジェクトです。マネージャーまたはサービス タイプのオブジェクトは、注入可能なオブジェクトの典型的な例です。
  • ニューアブルズは、DI グラフの端にあるオブジェクト、または実際には DI グラフの一部ではないオブジェクトです。IntegerなどAddressは、newable の例です。

大まかに言えば、newable は受動的なオブジェクトであり、注入したりモックしたりしても意味がありません。通常、newable にはアプリケーション内にあり、実行時にのみ利用可能な「データ」(アドレスなど) が含まれます。newable は injectable への参照を保持すべきではなく、その逆も同様です (投稿の著者はこれを「injectable/newable の分離」と呼んでいます)。

実際には、インジェクタブルとニューアブルを明確に区別することは必ずしも簡単ではない、または不可能であることがわかりました。それでも、これらは思考プロセスの一部として使用するのに適した概念だと思います。プロジェクトにさらに別のファクトリーを追加する前に、必ずよく考えてください。

Utilあなたの場合、を注入可能として扱い、アドレスを新規可能として扱うのが合理的だと思います。つまり、アドレスはUtilクラスの一部であってはなりません。たとえば、validating/... アドレスにインスタンスを使用する場合はUtil、検証するアドレスを、validation/... メソッドの引数として渡すだけです。

2021年からのアップデート

Dagger 2のバージョン2.31以降では、を使用した補助注入のメカニズムもあります@AssistedInject。詳細については、ドキュメントを参照してください。ここ(編集はジェイ・シドリ

おすすめ記事