Dependency Injection Container for Kotlin: Koin vs Kodein vs Dagger

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Dependency Injection Containers for Kotlin: Full Overview and Comparison

Dependency Injection (DI) is a key pattern in modern development that allows you to create loosely coupled, testable, and scalable applications. In the Kotlin ecosystem, there are several powerful DI containers, each with its own features. In this article, we will take a detailed look at the three most popular solutions: Koin, Kodein-DI, and Dagger/Hilt. You will learn how they work, their strengths and weaknesses, and which tool to choose for your project.



What is a Dependency Injection Container?

A DI container is a framework that manages the creation and lifecycle of objects (dependencies) and automatically injects them into classes. Instead of manually creating dependencies via a constructor or factory, you describe the assembly rules in modules, and the container handles all the routine work. This is especially useful in large projects with hundreds of classes.



1. Koin — Lightweight and Simple DI for Kotlin

Koin is a DSL-oriented DI container written in pure Kotlin. It does not require code generation, reflection, or annotations. All configuration is done through a convenient DSL (Domain Specific Language).



Installation

// build.gradle.ktsimplementation("io.insert-koin:koin-core:3.5.3")


Usage Example

// Define dependenciesval appModule = module {    single { HttpClient() }    factory { UserRepository(get()) }}

// Start Koinfun main() { startKoin { modules(appModule) } // Get dependency val repo: UserRepository by inject()}

class UserRepository(private val client: HttpClient)


Pros:

  • Minimal learning curve — no annotations, no code generation
  • Easy integration with Android (Koin Android)
  • Support for scopes (Scope API)
  • Fast compilation


Cons:

  • Errors are only detected at runtime
  • No compile-time dependency graph validation
  • Slightly slower than Dagger at runtime due to reflection


2. Kodein-DI — Flexible and Multiplatform

Kodein-DI is another DI framework written in pure Kotlin. It offers advanced features: support for multiplatform projects (KMP), lazy initialization, dependency tagging, and built-in factories.



Configuration Example

val di = DI {    bind<ApiService>() with singleton { RetrofitApiService() }    bind<Logger>() with provider { ConsoleLogger() }    bind<UserRepository>() with factory { UserRepositoryImpl(instance()) }}

// Usageclass MainActivity { private val repo: UserRepository by di.instance()}


Pros:

  • Full support for Kotlin Multiplatform (iOS, JS, JVM)
  • Powerful system of tags and modifiers
  • Ability to create nested containers
  • Support for scopes and thread safety


Cons:

  • Less popular than Koin (smaller community and fewer tutorials)
  • DSL may feel overloaded for simple projects
  • Also runtime dependency checking


3. Dagger / Hilt — High-Performance DI from Google

Dagger and its Android wrapper Hilt are DI frameworks based on compile-time code generation. They use annotations (@Inject, @Module, @Component) and generate all the binding code in advance. This provides maximum runtime performance.



Example with Hilt

@HiltAndroidAppclass MyApplication : Application()

@AndroidEntryPointclass MainActivity : AppCompatActivity() { @Inject latein

Recommendations