name: koin-module-wiring description: 'Koin dependency wiring pattern for AniTrend modules. Use when adding repository bindings, use case providers, module loaders, or app-level DI aggregation.'
Skill: Koin Module Wiring
Overview
Koin is the dependency injection framework used throughout AniTrend v2. Every feature or data
module exposes its bindings through a local Modules.kt file. Those local modules are collected
by the app-level aggregator and loaded at startup via InjectorInitializer.
For cross-layer Koin anchors, including Android platform modules, use the layer example matrix. Pair Android helper work with android-platform-patterns.
Registration precedence: register bindings in the Modules.kt file that belongs to the immediate
parent Gradle module first, then add that parent aggregator to app/core/src/main/kotlin/co/anitrend/core/koin/Modules.kt when the parent module is a new top-level module that must be loaded at startup.
Key files to read
app/core/src/main/kotlin/co/anitrend/core/initializer/injector/InjectorInitializer.kt— AndroidX Startup initializer that bootstraps Koin with all collected modulesapp/core/src/main/kotlin/co/anitrend/core/koin/Modules.kt— app-level Koin module aggregator; registers core singletons (Coil, Emoji, StateLayoutConfig, dispatchers, etc.)android/core/src/main/kotlin/co/anitrend/android/core/koin/Modules.kt— Android platform helpers such as settings, configuration, theme, notification, storage, shortcut, and power controllersandroid/navigation/src/main/kotlin/co/anitrend/android/navigation/drawer/koin/Modules.kt— app-shell drawer presenter/viewmodel/fragment/provider compositionandroid/deeplink/src/main/kotlin/co/anitrend/android/deeplink/koin/Modules.kt— deep-link parser, presenter, viewmodel, and provider compositiondata/src/main/kotlin/co/anitrend/data/tag/koin/— simple query-only example usingTagUseCaseImpldata/src/main/kotlin/co/anitrend/data/medialist/koin/Modules.kt— mutation-heavy example showing explicit typed mapper lookup for genericgraphQLController(...)bindingsdata/src/main/kotlin/co/anitrend/data/media/koin/Modules.kt— read-heavy example with operation-specific repository and interactor aliasesdata/src/main/kotlin/co/anitrend/data/review/koin/Modules.ktanddata/src/main/kotlin/co/anitrend/data/favourite/koin/Modules.kt— hybrid and mutation-only examplestask/review/src/main/kotlin/co/anitrend/task/review/koin/Modules.kt— worker bindings for task-backed mutation flows
Wiring checklist for a new module
- Create
<module>/src/main/kotlin/.../koin/Modules.ktwith avalthat returns a Koinmodule { }block. - Declare bindings using the exported aliases from the module
Types.ktwhere applicable:factory<MediaPagedRepository> { MediaRepository.Paged(source = get()) }factory<GetPagedMediaInteractor> { MediaInteractor.Paged(repository = get()) }
- Add feature or task entry bindings as needed:
viewModel { XxxViewModel(interactor = get(), ...) }worker { scope -> XxxWorker(context = androidContext(), parameters = scope.get(), interactor = get()) }- Android platform helpers: bind controllers, helpers, providers, or shell fragments in the
owning
:android:*module instead of a feature module
- Add the local module to the
Modules.ktfile in its immediate parent Gradle module so it gets loaded transitively. - If that parent Gradle module is new and must be loaded at app startup, also add its loader to
app/core/src/main/kotlin/co/anitrend/core/koin/Modules.kt. - Add or update a Koin resolution test for the changed binding. For central
:datawiring, prefer a focusedsrc/testcase that starts Koin with the relevant modules and resolves the exact contract you changed.
Rules
- Every public dependency must be exposed through Koin — no direct instantiation in feature code.
- In data modules, default to
factoryfor sources, mappers, converters, repositories, and interactors unless the dependency is intentionally app-wide state or configuration. Usesingleonly when the type is intentionally shared app-wide and an existing sibling module already binds it that way. - Use
get()to resolve transitive dependencies; never import concrete data-layer classes into a feature or task module's Koin file except for the worker or ViewModel class being declared. - When binding reusable Android-side helpers, keep the binding in
:android:*and letapp/core/src/main/kotlin/co/anitrend/core/koin/Modules.ktinclude the Android aggregator. - When a binding depends on a generic contract such as
graphQLController(mapper = ...)or a constructor parameter is declared as a broad interface or typealias, request the concrete dependency explicitly withget<ConcreteType>()instead of bareget(). Cover that path with a Koin resolution test. - Task Koin files should bind workers and router providers only. Repository, source, mapper, and controller bindings stay in the owning data module.