Skip to main content

Overview

This page gives you a solid understanding of what Anchor DI is, how it works under the hood, and what you get out of the box. If you're new to KMP or DI, read this before jumping into code.


What is Anchor DI?

Anchor DI is a compile-time dependency injection framework for Kotlin Multiplatform. It uses KSP (Kotlin Symbol Processing) to analyze your annotated code during compilation and generate a static dependency graph. No reflection, no runtime graph building — just generated Kotlin code that wires your dependencies together.

Think of it like Dagger or Hilt, but designed from the ground up for KMP. Same annotations (@Inject, @Module, @Provides, @Binds), same mental model, same compile-time safety — but it runs on Android, iOS, Desktop, and Web.


What Gets Validated at Compile Time?

One of the biggest advantages of compile-time DI is that many mistakes are caught before your app runs. Anchor DI validates the following during compilation:

ValidationWhat It Catches
Missing bindingsYou inject UserRepository but never provide it (no @Inject constructor, no @Provides, no @Binds). Build fails.
Dependency cyclesA depends on B, B depends on C, C depends on A. Build fails.
Scope violationsYou try to resolve a ViewModel-scoped type from the root container (e.g. Anchor.inject<UserRepository>() when UserRepository is ViewModel-scoped). Build fails.
Duplicate providersTwo modules provide the same type with the same qualifier. Build fails.
Invalid multibindingsDuplicate keys in @IntoMap, invalid @Binds shapes, etc. Build fails.

If the build succeeds, your dependency graph is valid. You won't see "No binding found" or "Scoped binding requires a scope" at runtime.


Key Features

FeatureDescriptionUse Case
Constructor injectionPut @Inject on constructors; Anchor DI resolves dependencies and creates instances.Your own classes (repositories, use cases, ViewModels)
ModulesUse @Module and @InstallIn to organize bindings. @Provides for manual creation, @Binds for interface → implementation.Third-party types, platform-specific types, complex construction
ScopesSingleton (app-wide), ViewModel (per screen), Navigation (per destination), custom (your lifecycle).Control object lifetime and avoid leaks
MultibindingContribute to Set<T> or Map<String, V> from multiple modules.Analytics trackers, plugins, interceptors
Compose integrationanchorInject() and viewModelAnchor() for Composables.Inject singletons or ViewModels in UI
KMP supportcommonMain, androidMain, iosMain, jvmMain, wasmJsMain. Use expect/actual for platform code.Shared logic across platforms

How Does It Work? (Architecture Overview)

Anchor DI follows a simple pipeline:

┌─────────────────────────────────────────────────────────────────────────┐
│ 1. You write annotated code: @Inject, @Module, @Provides, @Binds, etc. │
└─────────────────────────────────────────────────────────────────────────┘


┌─────────────────────────────────────────────────────────────────────────┐
│ 2. KSP runs during compilation. It discovers your classes and modules, │
│ validates the dependency graph, and generates a ComponentBinding │
│ Contributor that registers all bindings. │
└─────────────────────────────────────────────────────────────────────────┘


┌─────────────────────────────────────────────────────────────────────────┐
│ 3. At runtime, you call Anchor.init(*getAnchorContributors()). This │
│ builds the container with all bindings. │
└─────────────────────────────────────────────────────────────────────────┘


┌─────────────────────────────────────────────────────────────────────────┐
│ 4. You resolve dependencies: Anchor.inject<T>(), viewModelAnchor(), │
│ anchorInject(), etc. The container uses the generated factories │
│ to create instances. │
└─────────────────────────────────────────────────────────────────────────┘

No reflection in the hot path. Everything is generated code and direct calls.


Artifacts (What to Add to Your Project)

Anchor DI is split into multiple artifacts so you only include what you need:

ArtifactPurposeWhen to Use
anchor-di-apiAnnotations only (@Inject, @Module, @Provides, etc.). No runtime dependency.Always — your code references these.
anchor-di-coreContainer, runtime resolution, Anchor object.Always — this is the runtime.
anchor-di-kspKSP processor. Generates code at compile time.Always — needed for codegen.
anchor-di-composeCompose helpers: anchorInject(), viewModelAnchor(), NavigationScopedContent, navigationScopedInject().When using Compose Multiplatform for UI.
anchor-di-androidActivityScope and Android-specific helpers.When you need Activity-scoped DI on Android (with or without Compose).
anchor-di-presentationNavigationScopeRegistry (Compose-free).When you use KMP without Compose but need navigation-scoped DI (e.g. SwiftUI, Views).

Typical setup for Compose Multiplatform: anchor-di-api + anchor-di-core + anchor-di-compose + anchor-di-ksp.


Next Steps