Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dagger 2 injecting parameters of constructor

I saw the following example on the Dagger 2 website:

class Thermosiphon implements Pump {
  private final Heater heater;

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

  ...
}

and the documentation:

When a new instance is requested, Dagger will obtain the required parameters values and invoke this constructor.

When I write a Module to provide a Thermosiphon like

@Module
public class ThermosiphonModule {

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

}

the Thermosiphon constructor still requires a Heater as an argument, rendering the whole 'automatic injection of constructor dependencies' useless.

I tried

return new Thermosiphon(null); 

and

return new Thermosiphon(); 

(empty constructor) and hoped for Dagger2 to pick up that I wanted the missing Heater to be injected, yet the Heater of the provided Thermosiphon is always null;

I verified though my HeaterComponent / HeaterModule are working fine and are able to provide a Heater.

Do I completey misunderstand the whole feature of 'Dagger satisfies constructor dependencies for you' or am I missing something?

like image 473
fweigl Avatar asked Aug 18 '15 15:08

fweigl


People also ask

What does @inject do dagger?

Use @Inject to annotate the constructor that Dagger should use to create instances of a class. When a new instance is requested, Dagger will obtain the required parameters values and invoke this constructor. class Thermosiphon implements Pump { private final Heater heater; @Inject Thermosiphon(Heater heater) { this.

How do you inject value at runtime in dagger?

Inject values at runtime with UI in Dagger2:pureMathModule("Book Name") . build() . inject(this); The difference between DaggerComponent create() and in build() is - create() works when no runtime argument is passed into the constructor, else we use build() method.

What is @inject constructor Kotlin?

@Inject is a Java annotation for describing the dependencies of a class that is part of Java EE (now called Jakarta EE). It is part of CDI (Contexts and Dependency Injection) which is a standard dependency injection framework included in Java EE 6 and higher.

What does @inject constructor mean?

Constructor Injection is the act of statically defining the list of required dependencies by specifying them as parameters to the class's constructor.


2 Answers

If you're using modules, then if you have two provider modules bound to the same component, then you'll be able to allow them to see the heater as a constructor parameter.

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

But with constructor injection, you will also be able to provide objects of that given scope, or unscoped objects, as long as they have a @Inject constructor.

For example,

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

    void inject(Something something);
}

And

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

And

@Singleton
public class Thermosiphon {
    private Heater heater;

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

Or

@Singleton
public class Thermosiphon {
    @Inject
    Heater heater;

    @Inject
    public Thermosiphon() {
    }
}
like image 180
EpicPandaForce Avatar answered Oct 23 '22 03:10

EpicPandaForce


For one, since you've annotated the constructor of Thermosiphon with @Inject, you don't need an @Provides method. Dagger uses this constructor to create an instance when needed. Just annotate the Thermosiphon class itself with @Singleton to preserve the singleton behavior.

If you do want to use an @Provides method, and to answer your question fully, you can specify the Heater as a parameter to the method:

@Module
public class ThermosiphonModule {

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

}
like image 33
nhaarman Avatar answered Oct 23 '22 03:10

nhaarman