web-dev-qa-db-ja.com

短剣2コンストラクターのパラメーターの注入

Dagger 2 Webサイト で次の例を確認しました。

class Thermosiphon implements Pump {
  private final Heater heater;

  @Inject
  Thermosiphon(Heater heater) {
    this.heater = heater;
  }

  ...
}

およびドキュメント:

新しいインスタンスが要求されると、Daggerは必要なパラメーター値を取得し、このコンストラクターを呼び出します。

のようなThermosiphonを提供するモジュールを書くとき

@Module
public class ThermosiphonModule {

    @Provides
    @Singleton
    Thermosiphon provideThermosiphon() {
        return new Thermosiphon(???);
    }

}

Thermosiphonコンストラクターはまだ引数としてHeaterを必要とし、「コンストラクター依存関係の自動注入」全体を役に立たなくします。

私は試した

return new Thermosiphon(null); 

そして

return new Thermosiphon(); 

(空のコンストラクター)、不足しているHeaterを注入したいが、提供されたThermosiphonのヒーターは常にnullであることをDagger2が取得することを望みました。

HeaterComponent/HeaterModuleが正常に機能しており、Heaterを提供できることを確認しました。

「ダガーがコンストラクターの依存関係を満たしている」という機能全体を完全に誤解しているのですか、それとも何かが足りないのですか?

32
asco

モジュールを使用している場合、同じコンポーネントに2つのプロバイダーモジュールがバインドされていると、コンストラクターパラメーターとしてヒーターを表示できるようになります。

@Module
public class HeaterModule {
    @Provides
    @Singleton
    Heater heater() {
        return new Heater(); // if not using @Inject constructor
    }
}

@Module
public class ThermosiphonModule {
    @Provides
    @Singleton
    Thermosiphon thermosiphon(Heater heater) {
        return new Thermosiphon(heater); // if not using @Inject constructor
    }
}

@Singleton
@Component(modules={ThermosiphonModule.class, HeaterModule.class})
public interface SingletonComponent {
    Thermosiphon thermosiphon();
    Heater heater();

    void inject(Something something);
}

public class CustomApplication extends Application {
    private SingletonComponent singletonComponent;

    @Override
    public void onCreate() {
        super.onCreate();
        this.singletonComponent = DaggerSingletonComponent.builder().build(); //.create();
    }

    public SingletonComponent getSingletonComponent() {
        return singletonComponent;
    }
}

ただし、コンストラクターインジェクションを使用すると、@Injectコンストラクターがある限り、その特定のスコープのオブジェクトまたはスコープ外のオブジェクトを提供することもできます。

例えば、

@Singleton
@Component // no modules
public interface SingletonComponent {
    Thermosiphon thermosiphon();
    Heater heater();

    void inject(Something something);
}

そして

@Singleton
public class Heater {
    @Inject
    public Heater() {
    }
}

そして

@Singleton
public class Thermosiphon {
    private Heater heater;

    @Inject
    public Thermosiphon(Heater heater) {
        this.heater = heater;
    }
}

または

@Singleton
public class Thermosiphon {
    @Inject
    Heater heater;

    @Inject
    public Thermosiphon() {
    }
}
54
EpicPandaForce

1つには、Thermosiphonのコンストラクターに@Injectで注釈を付けているため、@Providesメソッドは不要です。 Daggerはこのコンストラクターを使用して、必要に応じてインスタンスを作成します。シングルトンの動作を維持するために、Thermosiphonクラス自体に@Singletonの注釈を付けてください。

@Providesメソッドを使用し、質問に完全に回答する場合は、Heaterをメソッドのパラメーターとして指定できます。

@Module
public class ThermosiphonModule {

    @Provides
    @Singleton
    Thermosiphon provideThermosiphon(Heater heater) {
        return new Thermosiphon(heater);
    }

}
29
nhaarman