I need to inject fields of an instance of one of my classes on-demand i.e., at runtime because I'm instantiating them on-the-fly.
I used to use Guice for this where I would call MembersInjector#injectMembers
or Injector#injectMembers
. How can I have something like this in Dagger 2?
Dagger 2 Components are the counterpart to Guice Injectors so the way to do this in Dagger 2 would be to specify the object whose field you want to inject at runtime as an injection site and request injection from the component.
Let's say you have a CoffeeShop with fields you want to inject:
class CoffeeShop {
@Inject CoffeeMaker coffeeMaker;
CoffeeShop() {
//we're not using constructor injection here
//although we probably should be :/
}
}
You can specify CoffeeShop as an injection site inside a component and request injection from it:
@Component(modules = { CoffeeModule.class })
interface CoffeeComponent {
void inject(CoffeeShop coffeeShop);
}
So inside another class you can do something like this:
private CoffeeComponent coffeeComponent;
void initComponent() {
coffeeComponent = DaggerCoffeeComponent
.builder()
.coffeeModule(new CoffeeModule())
.build();
}
void makeCoffee() {
CoffeeShop coffeeShop = new CoffeeShop();
coffeeComponent.inject(coffeeShop); //inject members of coffeeShop
coffeeShop.makeCoffee();
}
Alternatively, you can define provision methods inside your Dagger 2 Components which will allow you to resolve instances of a class ad hoc.
If you look at Jeff Bowman's example in the linked question, you can see there is a Component like this:
@Component(modules = {/* ... */})
public interface CoffeeShopComponent {
CoffeeShop getCoffeeShop();
void inject(CoffeeService serviceToInject); // to be discussed below
}
Say you then have a CoffeeService. You can now call getCoffeeShop()
to obtain arbitrary instances of CoffeeShop:
class CoffeeService extends SomeFrameworkService {
private CoffeeComponent coffeeComponent;
void initComponent() {
coffeeComponent = DaggerCoffeeComponent
.builder()
.coffeeModule(new CoffeeModule());
.build();
}
public CoffeeShop createCoffeeShop() {
return coffeeComponent.getCoffeeShop(); //equivalent to Injector.getInstance();
}
}