Reputation: 3969
Simplified UML diagram that describes by Components
architecture.
And there is an exception:
java.lang.IllegalArgumentException:
Multiple entries with same key:
gson=com.example.di.AppPresentationComponent and
gson=com.example.di.gamesession.GameSessionComponent
Dagger 2
cannot decide from which Component
provide an Gson
instance.
I never ever work with multiple inheritance. What can you recommend to solve my situation?
I can dispose of GameSessionComponent
and move gameSessionManager()
to GameSessionPresentationComponent
. It will work in my case, but it's sounds like a dirty solution.
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
}
Upvotes: 1
Views: 2437
Reputation: 21427
The Dagger user guide talks about two types of bindings:
Published bindings are those that provide functionality that is used by other parts of the application.
Internal bindings are the rest: bindings that are used in the implementation of some published type and that are not meant to be used except as part of it. These bindings are usually for package-private types or are qualified with package- private qualifiers.
You probably need to be thinking of this when you design your modules and components. What you currently have:
interface AppPresentationComponent : AppComponent
interface GameSessionComponent : AppComponent
interface GameSessionPresentationComponent : AppPresentationComponent
is a hierarchy where every component publishes all their bindings to the dependent components. This is quite confusing especially since your hierarchy of interfaces does not follow the hierarchy of components to dependent components. Set up like this, it is easy to get a duplicate binding. Ideally, you should not reach a situation where you have to reason about multiple inheritance for components.
At this stage, I would suggest you refactor your component interfaces so that they don't inherit from each other and you will be able to discover which bindings need to be published to dependent components and which can (and should) be internalized.
The same applies for your modules. Like a component, a module can both publish and internalize a binding. Why not bind GSON in another module at the ApplicationComponent
level and publish it to dependent components? Then you can get rid of the binding for GSON inside GameSessionModule
which seems to be causing the problem.
Upvotes: 2