Part 3: Simple Ways To Stab With Dagger 2 ( Method Injection, Constructor Injection)

Santosh Dhakal
4 min readJun 1, 2017

This is continuation from part 2 of Dagger 2 series

Method Injection

This is similar to the concept of setters in a class. In a normal setter, we do the following

SomeClass{ private CoffeeHelper coffeeHelper;
public void setCoffeeHelper(CoffeeHelper coffeeHelper){
this.coffeeHelper = coffeeHelper;
}
}
SomeClass someObject;
someObject.setCoffeeHelper( new CoffeeHelper )

Now with help of Dagger, it calls the function just like setter and whatever we want to do on that function is to ourself. Once we request Dagger for the object, it will now provide the object to our function. Rather than calling this function by ourselves, we provide this function to Dagger, so that Dagger can use it for giving the dependent object to us. Try to make this function be invoked by Dagger rather than invoking ourselves.

@Module
public class CoffeeProvider {

@Provides
CoffeeHelper getCoffeeHelper() {
return new CoffeeHelper();
}
}
@Component(modules = {CoffeeProvider.class})
public interface CoffeeComponent {
void provideCoffee(RestaurantA restaurantA);
}
//Restaurant Apublic CoffeeHelper coffeeHelper;

private void goDagger() {
CoffeeComponent coffeeComponent = DaggerCoffeeComponent.builder().build();
coffeeComponent.provideCoffee(this);
}

@Inject
public void setCoffeeMaker(CoffeeHelper coffeeHelper) {
//whatever we can do here is upto ourselves, Dagger will simply
// provide us with the requested dependent object here
this.coffeeHelper = coffeeHelper;
}

The only change on the generated classes ( in comparison to field injection ) will be in the MembersInjector class

public final class RestaurantA_MembersInjector implements MembersInjector<RestaurantA> {
private final Provider<CoffeeHelper> coffeeHelperProvider;

public RestaurantA_MembersInjector(Provider<CoffeeHelper> coffeeHelperProvider) {
//
this.coffeeHelperProvider = coffeeHelperProvider;
}

@Override
public void injectMembers(RestaurantA instance) {
//here it is simply calling the method of the instance
instance.setCoffeeMaker(coffeeHelperProvider.get());
}
}

Where as our CoffeeComponent implementation will be the same

public final class DaggerCoffeeComponent implements CoffeeComponent {
private Provider<CoffeeHelper> getCoffeeHelperProvider;

private MembersInjector<RestaurantA> restaurantAMembersInjector;

private DaggerCoffeeComponent(Builder builder) {
initialize(builder);
}

public static Builder builder() {
return new Builder();
}


@SuppressWarnings("unchecked")
private void initialize(final Builder builder) {

this.getCoffeeHelperProvider =
CoffeeProvider_GetCoffeeHelperFactory.create(builder.coffeeProvider);

this.restaurantAMembersInjector = RestaurantA_MembersInjector.create(getCoffeeHelperProvider);
}

@Override
public void provideCoffee(RestaurantA restaurantA) {
restaurantAMembersInjector.injectMembers(restaurantA);
}

public static final class Builder {
private CoffeeProvider coffeeProvider;

public CoffeeComponent build() {
if (coffeeProvider == null) {
this.coffeeProvider = new CoffeeProvider();
}
return new DaggerCoffeeComponent(this);
}
}
}

We can also pass all the dependent objects at once in the method injection

@Module
public class CoffeeProvider {

@Provides
CoffeeHelper getCoffeeHelper() {
return new CoffeeHelper();
}

@Provides
Coffee.Flavor getFlavor() {
return Coffee.Flavor.Espresso;
}
}
@Component(modules = {CoffeeProvider.class})
public interface CoffeeComponent {
void provideCoffee(RestaurantA restaurantA);
}
public CoffeeHelper coffeeHelper;

private void goDagger() {
CoffeeComponent coffeeComponent =
DaggerCoffeeComponent.builder().build();
coffeeComponent.provideCoffee(this);
}

@Inject
public void setCoffeeMaker(CoffeeHelper coffeeHelper, Coffee.Flavor flavor) {
this.coffeeHelper = coffeeHelper;
this.flavor = flavor;
}

All the codes of this example are in following links

Constructor Injection

Constructor Injection can be viewed in several ways. Let’s say we need CoffeeHelper object in our class HotelB. In this case, let us assume that the CoffeHelper object can be initialized in following manner only

public CoffeeHelper(Coffee.Flavor flavor,int waterQuantity){
this.waterQuantity = waterQuantity;
this.flavor = flavor;
}

So, for the object of CoffeeHelper, we need to provide Flavor and waterQuantity in it’s constructor. If any @module will provide the Flavor and waterQuantity then that module can also provide CoffeeHelper instance by constructor injection. Let us define our @module as

@Module
public class CoffeeProviderConstructor {
@Provides
public int quantities() {
return 10;
}

@Provides
public Coffee.Flavor getFlavor() {
return Coffee.Flavor.Americano;
}
}

which simply provides

  • an integer
  • and a Flavor

And if we modify the constructor of CoffeeHelper in following manner

@Inject
public CoffeeHelper(Coffee.Flavor flavor,int waterQuantity){
this.waterQuantity = waterQuantity;
this.flavor = flavor;
}

Here we have only added @Inject annotation. So by default our module CoffeeProviderConstructor can provide following

  • an integer
  • a Flavor
  • a CoffeeHelper object

The CoffeeHelper object by default is not provided by our Module. But since all the dependent objects needed for creating object of CoffeeHelper is provided by our Module, it can also provide CoffeeHelper object via constructor injection. And we can use any three of them in our HotelB class using method or using field injection

@Component(modules = {CoffeeProviderConstructor.class})
public interface CoffeeComp {
void injectCoffeeHelper(HotelB hotelB);
}

HotelB

@Inject
public CoffeeHelper coffeeHelper;
private void goDagger() {
CoffeeComp coffeeComp = DaggerCoffeeComp.builder().build();
coffeeComp.injectCoffeeHelper(this);
}

Let us look upon the generated Component classes as well

This is all for Constructor Injection. Here we have noticed that any @Provides inside @Module will generate a separate class. For instance in our CoffeeProvideConstructor there are two providers and as a result there are two separate generated provider classes

  • CoffeeProviderConstructor_GetFlavorFactory
  • CoffeeProviderConstructor_QuantitiesFactory

All the example source code can be found in following link

And overall source code for this blog post is in this link https://github.com/androidlife/get-a-fix-of-dependency/tree/constructor_method_injection. In next series we will focus on named providers and module dependencies.

--

--

Santosh Dhakal

Android app developer having a deep interest in mobile technology be it Android or iOS. Loves to learn ,share the knowledge and build things.