具有多个依赖项的Dagger2组件

13

这是我目前拥有的且能正常工作的内容:

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

    void inject(FragmentFacebookLogin fragment);
}

现在我想添加另一个依赖项。我将它改为这样:

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

但现在我得到了这个错误信息:

FragmentFacebookLoginComponent 依赖于不止一个有作用域的组件

我该怎样解决这个问题?我如何有多个依赖项?

如果我从一个组件中删除作用域,我会得到以下错误信息:

AnotherComponent(无作用域)不能依赖于有作用域的组件

5个回答

4
我在这里找到了答案:https://dev59.com/1V0b5IYBdhLWcg3wLOc2#29619594 最后,我创建了一个具有正确作用域的 AppComponent,并让 FacebookComponent 和 AnotherComponent 扩展此 AppComponent。
FacebookComponent 和 AnotherComponent 没有自己的作用域(我已经删除了它)。
现在看起来是这样的:
@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);
}

真的有效吗?对我来说有点奇怪。FacebookModule和AnotherModule提供了使用@AppScope作用域的对象? - afj88
@afj88 我不知道今天是否能够工作,但是两年前它是可以的。 - Ralph Bergmann

4

在依赖项数组中,您不能使用作用域组件(这相当奇怪,我必须说),只能使用非作用域组件或一个作用域组件 + 其他非作用域组件。但是,您可以使用“代理”接口欺骗dagger:

@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

但在构建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))

适用于dagger 2.13版本,其他版本不确定

此外,您还可以使用反向继承 ComponentA : ProxyComponentA 来消除创建 ProxyComponentAImpl 的需要,但如果您的 ComponentA 位于不同的 gradle 模块中,则这不是一个好的设计选择。

该解决方案受到以下问题讨论的启发: https://github.com/google/dagger/issues/1225


2

你希望被确定为ApplicationScope内的内容应该全部定义在没有作用域的情况下,并且只有在给定范围下的ApplicationComponent中才能在应用程序范围下链接在一起。

例如,

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

然后您可以执行以下操作。
@AppScope
@Component(dependencies={AnotherComponent.class, FacebookComponent.class})
public interface AppComponent extends AnotherComponent, FacebookComponent {}

之后您可以执行以下操作

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

请注意,未经作用域限制的提供程序会在每次注入调用时创建一个新实例。如果您需要作用域限制,则应将模块绑定到同一组件上,但组件只应依赖于其他组件以进行子作用域处理。

1
现在Dagger支持一个组件可以依赖于多个作用域范围内的依赖项。只需将您的Dagger版本更新到2.27即可。

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

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

0
在您的模块中包含依赖模块,如下所示:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接