Skip to main content
Version: 4.2

Kotlin Multiplatform Setup

This page sets up Koin in a Kotlin Multiplatform (KMP) project: Gradle dependencies, where the Koin code goes, one shared function that starts Koin, and how each platform calls it. It assumes you know modules and Starting Koin. How to give each platform its own implementations is covered in KMP Sharing Patterns.

Supported targets​

koin-core and the Compiler Plugin support every Kotlin target:

TargetSupported
AndroidYes
iOS (iosArm64, iosX64, iosSimulatorArm64)Yes
JVM (desktop, server)Yes
JS and Wasm (js, wasmJs)Yes
macOS, Linux, Windows (Kotlin/Native)Yes

Compose artifacts follow the targets of Compose Multiplatform. See the artifact table in Gradle Setup.

Dependencies​

Apply the Koin Compiler Plugin to the shared module and add Koin to the source sets:

// shared/build.gradle.kts
plugins {
kotlin("multiplatform")
alias(libs.plugins.koin.compiler)
}

kotlin {
androidTarget()
iosArm64()
iosSimulatorArm64()
jvm()

sourceSets {
commonMain.dependencies {
implementation(project.dependencies.platform(libs.koin.bom))
implementation(libs.koin.core)
implementation(libs.koin.annotations) // only with annotations

// Compose Multiplatform
implementation(libs.koin.compose)
implementation(libs.koin.compose.viewmodel)
}
androidMain.dependencies {
implementation(libs.koin.android)
}
commonTest.dependencies {
implementation(libs.koin.test)
}
}
}

The Compiler Plugin runs on every target from one declaration. There is no per-target configuration, unlike the KSP setup of Koin Annotations 1.x (see Migrating from KSP).

Project structure​

shared/
└── src/
├── commonMain/kotlin/di/
│ ├── Koin.kt // modules and initKoin()
│ └── PlatformModule.kt // expect declaration
├── androidMain/kotlin/di/
│ └── PlatformModule.android.kt
└── iosMain/kotlin/di/
└── PlatformModule.ios.kt
androidApp/ // Application class calls initKoin()
iosApp/ // Swift App calls initKoin()

Shared definitions live in commonMain. Each platform source set only contains what differs per platform.

Shared start function​

Write one function in commonMain that starts Koin. Each platform calls it, and can add its own configuration through the config parameter:

// commonMain/kotlin/di/Koin.kt
import org.koin.core.context.startKoin
import org.koin.dsl.KoinAppDeclaration
import org.koin.dsl.includes
import org.koin.dsl.module
import org.koin.plugin.module.dsl.*

val dataModule = module {
single<UserRepository>()
viewModel<UserViewModel>()
}

val appModule = module {
includes(dataModule, platformModule())
}

fun initKoin(config: KoinAppDeclaration? = null) {
startKoin {
includes(config)
modules(appModule)
}
}

includes(config) applies the platform configuration (Android context, logger, extra modules) to the same Koin start. platformModule() is an expect function, see KMP Sharing Patterns.

Platform entry points​

Android​

Call initKoin from your Application class and pass the Android context:

// androidApp
class MainApplication : Application() {
override fun onCreate() {
super.onCreate()
initKoin {
androidContext(this@MainApplication)
androidLogger()
}
}
}

Android definitions can then use Context as a constructor parameter. See Android Start.

iOS​

Add a function without parameters in iosMain, and call it from the Swift App initializer:

// iosMain/kotlin/di/KoinIos.kt
fun initKoinIos() = initKoin()
// iosApp/iOSApp.swift
import Shared

@main
struct iOSApp: App {
init() {
KoinIosKt.doInitKoinIos()
}

var body: some Scene {
WindowGroup { ContentView() }
}
}

Kotlin/Native naming rules explain the Swift call. Top-level functions of KoinIos.kt are exported in a class named KoinIosKt. A function whose name starts with init gets a do prefix, so initKoinIos becomes doInitKoinIos. The helper avoids passing a Kotlin lambda (config) from Swift.

Calling Koin from Swift code is covered in KMP Platform Integration.

JVM desktop​

// jvmMain
fun main() = application {
initKoin {
printLogger()
}
Window(onCloseRequest = ::exitApplication) {
App()
}
}

Web​

// jsMain or wasmJsMain
fun main() {
initKoin()
// start your UI
}

Compose Multiplatform​

With Compose Multiplatform, you can start Koin from the root Composable with KoinApplication instead of calling initKoin on each platform. On Android, it sets the Android context for you:

// commonMain
@Composable
fun App() {
KoinApplication(configuration = koinConfiguration { modules(appModule) }) {
MainScreen()
}
}

Keep initKoin if code outside Compose needs Koin before the first screen (a background service, Swift code). Both options are compared in Koin for Compose.