首页 > 解决方案 > Dagger2:如何在不注入合成器类的情况下注入字段?

问题描述

我的 A 类需要 C 类的依赖注入。C 类是 B 类的组件(B 具有 C 作为字段)。A类可以不注入B注入C吗?

[A 注入]->(B 未注入 A)->[C 注入 B]

我的真实项目我需要向一个类注入字段,但不需要向包含(直接或间接)该字段的所有类添加注入队列。

目前我在 B 类中有异常:

Exception in thread "main" java.lang.NullPointerException
        at B.log(B.java:28)
        at A.b_foo(A.java:28)
        at App.main(App.java:36)

请指教。代码:

应用程序.java

import dagger.Component;
import javax.inject.Singleton;
 
public class App {
  @Singleton
  @Component(
      modules = {
              CModule.class
             }
  )
  public interface AppRunner {
    A instance();
  }

  public static void main(String[] args) {
    AppRunner appRunner = DaggerApp_AppRunner.builder().build();
    appRunner.instance().foo();
  }
}

爪哇

import javax.inject.Inject;

public class A {
    private final B b;

    @Inject
    A() {
        this.b = new B();
    }

    public void foo() {
        b.log();
    }
}

B.java

import javax.inject.Inject;

public class B {

  @Inject
  C c;

  B() { }

  public void log() {
      c.log("in C log"); //java.lang.NullPointerException here because B was not injected before C
  }
}

C.java

import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.ArrayList;
import java.util.List;

@Singleton
public final class C {
  private final List<String> logs = new ArrayList<>();

  @Inject
  C() {}

  public void log(String msg) {
    logs.add(msg);
  }
}

CModule.java

import dagger.Module;
import dagger.Provides;

@Module
public abstract class CModule {
    @Provides
  static C provideC() {
        return new C();
    }
}

更新:我可以在没有 B 注入的情况下拥有完全工作的代码吗?我的A班知道Dagger。但是A必须没有B注入。

标签: javadagger-2

解决方案


您在 class 中有一个@Inject字段B,并且您希望能够在其中完全B初始化A

选项1:只需添加@Inject到构造函数

而已。您不需要将依赖项移动到构造函数中。

public class B {

  @Inject
  C c;

  @Inject // This annotation is the only thing added.
  B() { }

  public void log() {
      c.log("in C log");
  }
}

如果这超出了您想要更改(或可以更改)的范围B,请继续阅读。

选项 2:注入MembersInjector<B>

Dagger 包含 interface MembersInjector,它的功能与听起来完全一样。您可以注入MembersInjector<B>,并使用它分两步A构建。B

@Inject
A(MembersInjector<B> injector) {
    this.b = new B();
    injector.injectMembers(b);
}

由于MembersInjector它是 Dagger 而不是 JSR-330 的一部分,这意味着该类A必须了解 Dagger。这可能是一个问题,但您可以轻松地将此逻辑移出A

选项 3:MembersInjector@Provides方法中使用。

@Module
class BModule {
    @Provides
    static B provideB(MembersInjector<B> injector) {
        B b = new B();
        injector.injectMembers(b);
        return b;
    }
}

B现在您可以在任何地方注入Provider<B>,而无需进行任何修改B


推荐阅读