匕首2:具有相同键的多个条目

简短的解释

Components体系结构描述的简化的UML图。

在这里输入图像描述

还有一个例外:

 java.lang.IllegalArgumentException: Multiple entries with same key: gson=com.example.di.AppPresentationComponent and gson=com.example.di.gamesession.GameSessionComponent 

Dagger 2无法决定从哪个Component提供一个Gson实例。

我永远不会使用多重继承。 你能推荐什么来解决我的情况?

我可以处理GameSessionComponent并将gameSessionManager()移动到GameSessionPresentationComponent 。 它会在我的情况下工作,但这听起来像一个肮脏的解决方案。

有一些代码。

AppComponent:

 @PerApplication @Component(modules = arrayOf( AppModule::class, TextsModule::class, AudioModule::class, FontsModule::class, TexturesModule::class, QuestModule::class, GameSaveModule::class )) interface AppComponent { fun componentsHolder(): ComponentsHolder fun gdxContext(): GdxContext fun rxHelper(): RxHelper fun textsManager(): TextsManager fun soundsManager(): AudioManager fun fontsManager(): FontsManager fun texturesManager(): ThemesManager fun questManager(): QuestManager fun gameSaveManager(): GameSaveManager } 

AppPresentationComponent

 @PerApplicationPresentation @Component( dependencies = arrayOf(AppComponent::class), modules = arrayOf(AppPresentationModule::class) ) interface AppPresentationComponent : AppComponent { fun fonts(): Fonts fun audio(): Audio fun texts(): Texts fun textures(): Textures fun router(): KRQRouter fun launch(): LaunchScreen fun mainMenu(): MenuScreen fun settingsDialog(): SettingsDialog fun questInfoDialog(): InfoDialog } 

GameSessionComponent

 @PerGameSession() @Component( dependencies = arrayOf(AppComponent::class), modules = arrayOf(GameSessionModule::class) ) interface GameSessionComponent : AppComponent { fun storyTeller(): StoryTeller } 

GameSessionPresentationComponent

 @PerGameSessionPresentation @Component( dependencies = arrayOf(AppPresentationComponent::class), modules = arrayOf(GameSessionPresentationModule::class, GameSessionModule::class) ) interface GameSessionPresentationComponent : AppPresentationComponent { fun storyTeller(): StoryTeller fun story(): StoryScreen fun gameoverDialog(): GameoverDialog fun inGameMenu(): InGameMenu fun donateDialog(): DonateDialog } 

Dagger用户指南讨论了两种类型的绑定:

已发布的绑定是那些提供应用程序其他部分使用的功能的绑定。

内部绑定是其余部分:用于实现某些已发布类型的绑定,除了作为其一部分外,不打算使用。 这些绑定通常用于包私有类型或用包私有限定符限定。

设计模块和组件时,您可能需要考虑这一点。 你目前有什么:

 interface AppPresentationComponent : AppComponent interface GameSessionComponent : AppComponent interface GameSessionPresentationComponent : AppPresentationComponent 

是每个组件所有绑定发布到相关组件的层次结构。 这是相当混乱的,尤其是因为您的接口层次结构不遵循组件到依赖组件的层次结构。 像这样设置,很容易获得重复的绑定。 理想情况下,你不应该达到你必须推理组件的多重继承的情况。

在这个阶段,我会建议你重构你的组件接口,使它们不会相互继承,你将能够发现哪些绑定需要发布到依赖组件,哪些可以(也应该)被内化。

这同样适用于你的模块。 就像一个组件一样,一个模块可以发布和内部化一个绑定。 为什么不在ApplicationComponent级别的另一个模块中绑定GSON并将其发布到相关组件? 然后你可以摆脱GameSessionModule里面的GameSessionModule绑定,这似乎是造成这个问题的原因。