web-dev-qa-db-fra.com

Dague 2 injectant les paramètres du constructeur

J'ai vu l'exemple suivant sur le site Web Dagger 2 :

class Thermosiphon implements Pump {
  private final Heater heater;

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

  ...
}

et la documentation:

Lorsqu'une nouvelle instance est demandée, Dagger obtiendra les valeurs de paramètres requises et invoquera ce constructeur.

Quand j'écris un module pour fournir un Thermosiphon comme

@Module
public class ThermosiphonModule {

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

}

le constructeur Thermosiphon nécessite toujours un Heater comme argument, rendant inutile toute "l'injection automatique des dépendances du constructeur".

J'ai essayé

return new Thermosiphon(null); 

et

return new Thermosiphon(); 

(constructeur vide) et espérait que Dagger2 capterait que je voulais que le Heater manquant soit injecté, mais le chauffage du Thermosiphon fourni est toujours nul;

J'ai vérifié que mes HeaterComponent/HeaterModule fonctionnent bien et sont capables de fournir un Heater.

Est-ce que je comprends mal toute la fonctionnalité de "Dagger satisfait les dépendances des constructeurs pour vous" ou est-ce que je manque quelque chose?

32
asco

Si vous utilisez des modules, alors si vous avez deux modules fournisseur liés au même composant, vous pourrez leur permettre de voir le réchauffeur comme un paramètre constructeur.

@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;
    }
}

Mais avec l'injection de constructeur, vous serez également en mesure de fournir des objets de cette portée donnée, ou des objets non étendus, tant qu'ils ont un @Inject constructeur.

Par exemple,

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

    void inject(Something something);
}

Et

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

Et

@Singleton
public class Thermosiphon {
    private Heater heater;

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

Ou

@Singleton
public class Thermosiphon {
    @Inject
    Heater heater;

    @Inject
    public Thermosiphon() {
    }
}
54
EpicPandaForce

D'une part, puisque vous avez annoté le constructeur de Thermosiphon avec @Inject, vous n'avez pas besoin d'un @Provides méthode. Dagger utilise ce constructeur pour créer une instance en cas de besoin. Annotez simplement la classe Thermosiphon avec @Singleton pour conserver le comportement singleton.

Si vous souhaitez utiliser un @Provides, et pour répondre pleinement à votre question, vous pouvez spécifier Heater comme paramètre de la méthode:

@Module
public class ThermosiphonModule {

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

}
29
nhaarman