繁体   English   中英

Dagger2:如何在不注入其合成器类的情况下注入字段?

[英]Dagger2: How to inject field without injection of it's compositor class?

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

一个.java

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

模块

import dagger.Module;
import dagger.Provides;

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

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

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

选项 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 包含接口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:在@Provides方法中使用MembersInjector

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

现在你可以在任何地方注入BProvider<B> ,根本不需要修改B

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM