简体   繁体   English

具有多个依赖项的 Dagger2 组件

[英]Dagger2 component with more than one dependencies

This is what I currently have and it works:这是我目前拥有的并且有效:

@FragmentScope
@Component(dependencies = {FacebookComponent.class}, 
           modules = {FragmentFacebookLoginModule.class})
public interface FragmentFacebookLoginComponent {

    void inject(FragmentFacebookLogin fragment);
}

Now I want to add another dependency.现在我想添加另一个依赖项。 I changed it to this:我把它改成这样:

@Component(dependencies = {FacebookComponent.class, AnotherComponent.class}, 
           modules = {FragmentFacebookLoginModule.class})

But now I get this error message:但现在我收到此错误消息:

FragmentFacebookLoginComponent depends on more than one scoped component FragmentFacebookLoginComponent 依赖于多个作用域组件

How can I solve this?我该如何解决这个问题? How can I have more than one dependencies?我如何拥有多个依赖项?

If I remove the scope from one component I get this error message:如果我从一个组件中删除范围,我会收到以下错误消息:

AnotherComponent (unscoped) cannot depend on scoped components AnotherComponent (unscoped) 不能依赖于作用域的组件

I found the answer here: https://stackoverflow.com/a/29619594/1016472我在这里找到了答案: https : //stackoverflow.com/a/29619594/1016472

At the end I created a AppComponent with the right scope and let FacebookComponent and AnotherComponent extends this AppComponent.最后,我创建了一个具有正确范围的 AppComponent,并让 FacebookComponent 和 AnotherComponent 扩展了这个 AppComponent。

FacebookComponent and AnotherComponent does not have it's own scope (I removed it). FacebookComponent 和 AnotherComponent 没有它自己的范围(我删除了它)。

Looks now like this:现在看起来像这样:

@AppScope
@Component
public interface AppComponent {

}


@Component(modules = {FacebookModule.class})
public interface FacebookComponent extends AppComponent {

}


@Component(modules = {AnotherModule.class})
public interface AnotherComponent extends AppComponent {

}


@FragmentScope
@Component(dependencies = {FacebookComponent.class, AnotherComponent.class}, 
           modules = {FragmentFacebookLoginModule.class})
public interface FragmentFacebookLoginComponent {

    void inject(FragmentFacebookLogin fragment);
}

You can't use scoped components in a dependencies array (which is quite strange I have to say), only unscoped, or one scoped + other unscoped.您不能在依赖项数组中使用作用域组件(我不得不说这很奇怪),只能使用无作用域,或一个作用域 + 其他无作用域。 But you can deceive dagger with "proxy" interfaces:但是你可以用“代理”接口欺骗匕首:

@Component
@Singleton
interface ComponentA {
    fun provideSomeA()
}

interface ProxyComponentA : ComponentA

@Component
@Singleton
interface ComponentB {
    fun provideSomeB()
}

interface ProxyComponentB : ComponentB

@Component(dependencies = [ProxyComponentA::class, ProxyComponentB::class])
@OtherScope
interface ComponentC

But in your ComponentC builder you should use proxy components implementations, which could easily be achieved with Kotlin:但是在您的 ComponentC 构建器中,您应该使用代理组件实现,这可以通过 Kotlin 轻松实现:

class ProxyComponentAImpl(private val delegate: ComponentA) : ProxyComponentA, ComponentA by delegate
class ProxyComponentBImpl(private val delegate: ComponentB) : ProxyComponentB, ComponentB by delegate

componentA = DaggerComponentA.builder()...
componentB = DaggerComponentB.builder()...

componentC = DaggerComponentC.builder()
                   .componentA(ProxyComponentAImpl(componentA))
                   .componentB(ProxyComponentBImpl(componentB))

Works on dagger version 2.13, don't know about others适用于 dagger 2.13 版,不知道其他的

Also you could use vice versa inheritance ComponentA : ProxyComponentA to eliminate the need to create ProxyComponentAImpl, but it's not a good design choice if your ComponentA lays for example in a different gradle module您也可以使用相反的继承 ComponentA : ProxyComponentA 来消除创建 ProxyComponentAImpl 的需要,但如果您的 ComponentA 位于不同的 gradle 模块中,这不是一个好的设计选择

The solution was inspired by that issue discussion: https://github.com/google/dagger/issues/1225该解决方案的灵感来自该问题讨论: https : //github.com/google/dagger/issues/1225

What you want to be determined to be within the ApplicationScope should be all defined without a scope, and linked together under the application scope only in the ApplicationComponent under the given scope.你想确定在ApplicationScope内的东西,应该都是不带作用域定义的,只在给定作用域下的ApplicationComponent在应用作用域下链接在一起。

For example,例如,

@Component(modules = {FacebookModule.class})
public interface FacebookComponent {
    FacebookThing facebookThing(); //assuming this is with @Provides in FacebookModule with NO SCOPE
}


@Component(modules = {AnotherModule.class})
public interface AnotherComponent{
    AnotherThing anotherThing(); //assuming this is with @Provides in AnotherModule with NO SCOPE
}

Then you can do然后你可以做

@AppScope
@Component(dependencies={AnotherComponent.class, FacebookComponent.class})
public interface AppComponent extends AnotherComponent, FacebookComponent {}

After which you can do之后你可以做

@FragmentScope
@Component(dependencies=AppComponent.class)
public interface FragmentComponent extends AppComponent {}

Please note that unscoped providers create a new instance on every inject call.请注意,无作用域的提供者在每次注入调用时都会创建一个新实例。 If you need the scoping, you should bind the modules to the same component, but components should only depend on other components with the intention of subscoping.如果您需要作用域,您应该将模块绑定到同一个组件,但组件应该只依赖于具有子作用域的其他组件。

Now Dagger supports a component that can depends on more than 1 scoped dependencies.现在 Dagger 支持一个可以依赖于 1 个以上作用域依赖项的组件。 Just update your dagger version to 2.27只需将您的匕首版本更新到 2.27

https://github.com/google/dagger/issues/1414 https://github.com/google/dagger/issues/1414

api 'com.google.dagger:dagger:2.27'
kapt 'com.google.dagger:dagger-compiler:2.27'

Include on your module the dependency module like this:在你的模块中包含这样的依赖模块:

@Module(includes = FacebookModule.class)
public class AnotherModule {...

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

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