有没有办法告诉Dagger 2如何提供某些东西,但不允许它被注入?
我想要注入一个Qux
。 Qux
需要Foo
和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);
}
但是,如果我不希望Foo
和Bar
可注射,该怎么办?也许暴露它们会破坏Qux
的封装,或者它们可能是我只希望Qux
可以访问的某种工厂。
我想过几种方法可以做到这一点:
Foo
单例,我可以将其作为类成员。但如果Foo
有多个自己的依赖关系,这会变得混乱。Bar
单例,我可以在Qux
提供程序中创建实例。但如果Qux
有几个依赖性,那么这会变得混乱。这些解决方案似乎都不是很优雅或者是Daggery。还有另一种方式吗?
答案 0 :(得分:1)
我说这听起来很像component dependencies。
[..]作为替代方案,组件只能通过声明组件依赖关系来使用来自另一个组件接口的绑定。当类型用作组件依赖项时,依赖项上的每个提供方法都绑定为提供程序。请注意,只有通过组件依赖性提供作为提供方法公开的绑定。
如果您确实要隐藏Bar
和Foo
,可以将模块Bar
和Qux
打包到本地。然后创建一个仅公开Foo
的组件,并将其用作组件依赖项。
由于Bar
和SubComponent
是本地包,因此Foo
也不应该使用它们。
您的组件将是唯一能够使用该模块的组件,从而在其依赖关系图中创建并使用Bar
和import {MultiselectDropdown, IMultiSelectOption} from 'multiselect-dropdown';
。
答案 1 :(得分:1)
实现您尝试做的最简单方法是定义一个包私有限定符。
package my.pkg;
@Qualifier
@Retention(RUNTIME)
@interface ForMyPackage {}
然后,将其用于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);
}
这样,如果您有权访问限定符,则只能请求注入那些版本的Foo和Bar。
如果所有这些绑定都在一个模块中,您甚至可以在模块中使用私有的嵌套限定符。
由提问者编辑:
我尝试了最后一个建议。
@Qualifier
@Retention(RUNTIME)
private @interface NoInject {}
@Provides
@Singleton
@NoInject
Foo foo() { return new Foo(); }
尝试注入Foo
会导致编译时错误:
错误:(15,6)Gradle:错误:如果没有@Inject构造函数或@ Provide-或@ Produces-annotated方法,则无法提供com.mydomain.myapp.Foo。 com.mydomain.myapp.MyActivity.foo [注入字段类型:com.mydomain.myapp.Foo foo]
因此,虽然错误消息有点误导,但这种技术很简洁有效。
答案 2 :(得分:0)
在其他地方转发我的答案...
一个简单的方法是:
@Retention(BINARY)
@Qualifier
private annotation class InternalApi
@Module
object NetworkModule {
@Provides
@InternalApi
fun provideClient(): OkHttpClient {
//...
}
@Provides
fun provideRetrofit(
@InternalApi client: Lazy<OkHttpClient>
): Retrofit {
//...
}
}
从here中剔除。
基本上,我们创建私有限定符-在这种情况下,@InternalApi
用于限定OkHttpClient
依赖关系,从而使其对我们的模块私有。