具有多个依赖项的 Dagger2 组件
Dagger2 component with more than one dependencies
这是我目前拥有的并且有效:
@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 depends on more than one scoped
component
我该如何解决这个问题?我怎样才能拥有多个依赖项?
如果我从一个组件中删除范围,我会收到此错误消息:
AnotherComponent (unscoped) cannot depend on scoped components
我在这里找到了答案:
最后我创建了一个具有正确作用域的 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);
}
你要确定在ApplicationScope
内的,应该都是在没有作用域的情况下定义的,只在给定作用域下的ApplicationComponent
中在application作用域下链接在一起。
例如,
@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 {}
请注意,未定义范围的提供程序会在每次注入调用时创建一个新实例。如果你需要范围,你应该将模块绑定到同一个组件,但组件应该只依赖于其他组件以实现子范围。
在您的模块中包含这样的依赖模块:
@Module(includes = FacebookModule.class)
public class AnotherModule {...
您不能在依赖项数组中使用作用域组件(我不得不说这很奇怪),只能使用非作用域组件,或者一个作用域组件 + 其他非作用域组件。
但是你可以用 "proxy" 接口来欺骗 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
现在 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'
这是我目前拥有的并且有效:
@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 depends on more than one scoped component
我该如何解决这个问题?我怎样才能拥有多个依赖项?
如果我从一个组件中删除范围,我会收到此错误消息:
AnotherComponent (unscoped) cannot depend on scoped components
我在这里找到了答案:
最后我创建了一个具有正确作用域的 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);
}
你要确定在ApplicationScope
内的,应该都是在没有作用域的情况下定义的,只在给定作用域下的ApplicationComponent
中在application作用域下链接在一起。
例如,
@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 {}
请注意,未定义范围的提供程序会在每次注入调用时创建一个新实例。如果你需要范围,你应该将模块绑定到同一个组件,但组件应该只依赖于其他组件以实现子范围。
在您的模块中包含这样的依赖模块:
@Module(includes = FacebookModule.class)
public class AnotherModule {...
您不能在依赖项数组中使用作用域组件(我不得不说这很奇怪),只能使用非作用域组件,或者一个作用域组件 + 其他非作用域组件。 但是你可以用 "proxy" 接口来欺骗 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
现在 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'