Dagger 2依赖可以不可注射吗?

时间:2016-08-30 05:19:25

标签: dagger-2

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

我想要注入一个QuxQux需要FooBar

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

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

我想过几种方法可以做到这一点:

  • 如果其他提供商需要Foo单例,我可以将其作为类成员。但如果Foo有多个自己的依赖关系,这会变得混乱。
  • 如果任何其他提供者不需要Bar单例,我可以在Qux提供程序中创建实例。但如果Qux有几个依赖性,那么这会变得混乱。

这些解决方案似乎都不是很优雅或者是Daggery。还有另一种方式吗?

3 个答案:

答案 0 :(得分:1)

我说这听起来很像component dependencies

  

[..]作为替代方案,组件只能通过声明组件依赖关系来使用来自另一个组件接口的绑定。当类型用作组件依赖项时,依赖项上的每个提供方法都绑定为提供程序。请注意,只有通过组件依赖性提供作为提供方法公开的绑定。

如果您确实要隐藏BarFoo,可以将模块BarQux打包到本地。然后创建一个仅公开Foo的组件,并将其用作组件依赖项。

由于BarSubComponent是本地包,因此Foo也不应该使用它们。
您的组件将是唯一能够使用该模块的组件,从而在其依赖关系图中创建并使用Barimport {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依赖关系,从而使其对我们的模块私有。