【问题标题】:Dagger2 component with more than one dependencies具有多个依赖项的 Dagger2 组件
【发布时间】:2015-05-23 23:40:15
【问题描述】:

这是我目前拥有的,并且有效:

@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 依赖于多个作用域 组件

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

如果我从一个组件中删除范围,我会收到以下错误消息:

另一个组件(无作用域)不能依赖作用域组件

【问题讨论】:

    标签: java android dagger-2


    【解决方案1】:

    现在 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'
    

    【讨论】:

      【解决方案2】:

      您不能在依赖项数组中使用作用域组件(我不得不说这很奇怪),只能使用非作用域,或者一个作用域 + 另一个未作用域。 但是你可以用“代理”接口欺骗匕首:

      @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

      【讨论】:

        【解决方案3】:

        你要确定在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 {}
        

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

        【讨论】:

          【解决方案4】:

          我在这里找到了答案:https://stackoverflow.com/a/29619594/1016472

          最后我创建了一个具有正确范围的 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 我不知道它今天是否有效,但它在 2 年前有效
          【解决方案5】:

          在你的模块中包含这样的依赖模块:

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2022-10-20
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多