Dagger 2 依赖项可以是不可注入的吗?

Kev*_*ede 5 dagger-2

有没有办法告诉 Dagger 2 如何提供某些东西,但不允许它被注入?

假设我想注入一个Qux. AQux需要 aFoo和 a Bar

@Provides
@Singleton
Foo foo() {
    return new Foo();
}

@Provides
@Singleton
Bar bar() {
    return new Bar();
}

@Provides
@Singleton
Qux qux(final Foo foo, final Bar bar) {
    return new Qux(foo, bar);
}
Run Code Online (Sandbox Code Playgroud)

但如果我不想注射怎么FooBar?也许暴露它们会破坏 的封装,或者它们可能是我只想访问的Qux某种工厂。Qux

我想到了几种可以实现这一目标的方法:

  • 如果Foo其他提供者需要该单例,我可以将其设为类成员。Foo但如果它自己有几个依赖项,这会变得混乱。
  • 如果Bar任何其他提供程序不需要该单例,我可以在Qux提供程序内创建实例。但如果Qux有多个这样的依赖项,这会变得混乱。

这些解决方案看起来都不是非常优雅或危险。还有别的办法吗?

gk5*_*885 2

实现您想要做的事情的最简单方法是定义一个包私有限定符。

package my.pkg;

@Qualifier
@Retention(RUNTIME)
@interface ForMyPackage {}
Run Code Online (Sandbox Code Playgroud)

然后,将其用于 Foo 和 Bar 的绑定:

@Provides
@Singleton
@ForMyPackage
Foo foo() {
    return new Foo();
}

@Provides
@Singleton
@ForMyPackage
Bar bar() {
    return new Bar();
}

@Provides
@Singleton
Qux qux(final @ForMyPackage Foo foo, final @ForMyPackage Bar bar) {
    return new Qux(foo, bar);
}
Run Code Online (Sandbox Code Playgroud)

这样,如果您有权访问限定符,则只能请求注入 Foo 和 Bar 的这些版本。

如果所有这些绑定都在单个模块中,您甚至可以在模块中使用私有的嵌套限定符。

提问者编辑:

我尝试了最后一个建议。

@Qualifier
@Retention(RUNTIME)
private @interface NoInject {}

@Provides
@Singleton
@NoInject
Foo foo() { return new Foo(); }
Run Code Online (Sandbox Code Playgroud)

根据需要,尝试注入 aFoo会导致编译时错误:

错误:(15, 6) Gradle:错误:如果没有 @Inject 构造函数或从 @Provides- 或 @Produces- 注解的方法,则无法提供 com.mydomain.myapp.Foo。com.mydomain.myapp.MyActivity.foo [注入字段类型:com.mydomain.myapp.Foo foo]

因此,虽然错误消息有点误导,但这种技术简洁有效。