如何使用 Dagger 2 在运行时注入字段?

How do I inject fields at runtime using Dagger 2?

我需要按需注入我的 类 之一的实例的字段,即在运行时,因为我正在即时实例化它们。

我过去常常使用 Guice 来调用 MembersInjector#injectMembers or Injector#injectMembers。我怎么能在 Dagger 2 中拥有这样的东西?

Dagger 2 Components 是 Guice Injectors 的对应物,因此在 Dagger 2 中执行此操作的方法是指定要在运行时将其字段注入的对象作为注入站点,并从组件。

假设您有一家 CoffeeShop,其中包含您要注入的字段:

class CoffeeShop {

    @Inject CoffeeMaker coffeeMaker;

    CoffeeShop() { 
        //we're not using constructor injection here 
        //although we probably should be :/
    }
}

您可以将 CoffeeShop 指定为组件内的注入站点并请求从中注入:

@Component(modules = { CoffeeModule.class })
interface CoffeeComponent {
    void inject(CoffeeShop coffeeShop);
}

所以在另一个 class 中你可以这样做:

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();
}

或者,您可以在 Dagger 2 组件中定义 ,这将允许您临时解析 class 实例。

如果您查看链接问题中的 Jeff Bowman's 示例,您可以看到有一个这样的组件:

@Component(modules = {/* ... */})
public interface CoffeeShopComponent {
  CoffeeShop getCoffeeShop();

  void inject(CoffeeService serviceToInject); // to be discussed below
}

假设您有一个 CoffeeService。您现在可以调用 getCoffeeShop() 来获取 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();
    }
}

我不知道 Dagger2 在发布此问题时在 @Subcomponent.Factory@Component.Factory 中支持 @BindsInstance,但无论如何,目前最好的注入实例的方法在运行时似乎正在使用这些。

在 Dagger2 教程中,有一个示例(https://dagger.dev/tutorial/10-deposit-after-login)创建一个接收实例的子组件。