Skip to main content
Version: 4.2

Kotlin Multiplatform Setup

Koin provides first-class support for Kotlin Multiplatform (KMP) projects. This guide covers setup and configuration.

Supported Platforms

PlatformStatus
Android✅ Full support
iOS (arm64, x64, simulatorArm64)✅ Full support
JVM✅ Full support
JS✅ Full support
Wasm✅ Full support
macOS✅ Full support
Linux✅ Full support
Windows✅ Full support

Dependencies Setup

shared/build.gradle.kts

plugins {
kotlin("multiplatform")
id("io.insert-koin.compiler.plugin") // Optional: for Compiler Plugin
}

kotlin {
androidTarget()
iosX64()
iosArm64()
iosSimulatorArm64()
jvm()
js(IR) { browser() }

sourceSets {
commonMain.dependencies {
implementation(platform("io.insert-koin:koin-bom:4.2.0"))
implementation("io.insert-koin:koin-core")
}

commonTest.dependencies {
implementation("io.insert-koin:koin-test")
}

androidMain.dependencies {
implementation("io.insert-koin:koin-android")
}
}
}

With Compose Multiplatform

kotlin {
sourceSets {
commonMain.dependencies {
implementation(platform("io.insert-koin:koin-bom:4.2.0"))
implementation("io.insert-koin:koin-core")
implementation("io.insert-koin:koin-compose")
implementation("io.insert-koin:koin-compose-viewmodel")
}
}
}

Project Structure

project/
├── shared/
│ ├── src/
│ │ ├── commonMain/
│ │ │ └── kotlin/
│ │ │ ├── di/
│ │ │ │ └── KoinModules.kt
│ │ │ └── domain/
│ │ │ └── UserRepository.kt
│ │ ├── androidMain/
│ │ │ └── kotlin/
│ │ │ └── di/
│ │ │ └── PlatformModule.android.kt
│ │ └── iosMain/
│ │ └── kotlin/
│ │ └── di/
│ │ └── PlatformModule.ios.kt
│ └── build.gradle.kts
├── androidApp/
│ └── src/main/kotlin/
│ └── MainApplication.kt
└── iosApp/
└── iOSApp.swift

Common Module Definition

commonMain/kotlin/di/KoinModules.kt

import org.koin.dsl.module

// Shared definitions
val sharedModule = module {
single<UserRepository>()
single<ApiClient>()
factory<GetUserUseCase>()
}

// Platform-specific modules (defined per platform)
expect val platformModule: Module

Platform-Specific Modules

androidMain/kotlin/di/PlatformModule.android.kt

import org.koin.dsl.module

actual val platformModule = module {
single<PlatformHelper> { AndroidPlatformHelper() }
single<DatabaseDriver> { AndroidDatabaseDriver(get()) }
}

iosMain/kotlin/di/PlatformModule.ios.kt

import org.koin.dsl.module

actual val platformModule = module {
single<PlatformHelper> { IosPlatformHelper() }
single<DatabaseDriver> { IosDatabaseDriver() }
}

Shared Initialization

commonMain/kotlin/di/KoinInit.kt

import org.koin.core.context.startKoin
import org.koin.core.KoinApplication

fun initKoin(config: KoinAppDeclaration? = null): KoinApplication {
return startKoin {
includes(config)
modules(
sharedModule,
platformModule
)
}
}

Platform Entry Points

Android

// androidApp/src/main/kotlin/MainApplication.kt
class MainApplication : Application() {
override fun onCreate() {
super.onCreate()

initKoin {
androidContext(this@MainApplication)
androidLogger()
}
}
}

iOS

// shared/src/iosMain/kotlin/di/KoinInitIos.kt
fun initKoinIos() {
initKoin()
}
// iosApp/iOSApp.swift
import shared

@main
struct iOSApp: App {
init() {
KoinInitIosKt.initKoinIos()
}

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

JVM

fun main() {
initKoin {
printLogger()
}

val repository: UserRepository = get()
}

Using Expect/Actual

Common Interface

// commonMain
interface PlatformHelper {
fun getPlatformName(): String
fun getDeviceId(): String
}

Platform Implementations

// androidMain
class AndroidPlatformHelper(private val context: Context) : PlatformHelper {
override fun getPlatformName() = "Android"
override fun getDeviceId() = Settings.Secure.getString(
context.contentResolver,
Settings.Secure.ANDROID_ID
)
}

// iosMain
class IosPlatformHelper : PlatformHelper {
override fun getPlatformName() = "iOS"
override fun getDeviceId() = UIDevice.currentDevice.identifierForVendor?.UUIDString ?: ""
}

Module Definition

// commonMain
val platformModule = module {
single<PlatformHelper> { getPlatformHelper() }
}

expect fun getPlatformHelper(): PlatformHelper

// androidMain
actual fun getPlatformHelper(): PlatformHelper = AndroidPlatformHelper(get())

// iosMain
actual fun getPlatformHelper(): PlatformHelper = IosPlatformHelper()

Compiler Plugin with KMP

The Compiler Plugin simplifies KMP setup (no per-platform KSP configuration):

// settings.gradle.kts
plugins {
id("io.insert-koin.compiler.plugin") version "1.0.0" apply false
}

// shared/build.gradle.kts
plugins {
kotlin("multiplatform")
id("io.insert-koin.compiler.plugin")
}

Use Compiler Plugin DSL:

// commonMain
val sharedModule = module {
single<UserRepository>()
single<ApiClient>()
factory<GetUserUseCase>()
}

Annotations with KMP

// commonMain
@Singleton
class UserRepository(private val api: ApiClient)

@Factory
class GetUserUseCase(private val repository: UserRepository)

@Module
@ComponentScan("com.myapp")
class SharedModule

Testing in KMP

commonTest

class UserRepositoryTest : KoinTest {
private val repository: UserRepository by inject()

@BeforeTest
fun setup() {
startKoin {
modules(testModule)
}
}

@AfterTest
fun teardown() {
stopKoin()
}

@Test
fun testGetUser() {
val user = repository.getUser("123")
assertEquals("Test User", user.name)
}
}

val testModule = module {
single<ApiClient> { MockApiClient() }
single<UserRepository>()
}

Best Practices

  1. Put shared code in commonMain - Business logic, repositories, use cases
  2. Use expect/actual for platform specifics - File system, device APIs, platform libraries
  3. Initialize Koin per platform - Each platform has its entry point
  4. Share modules where possible - Define modules in commonMain
  5. Keep platform modules minimal - Only what's truly platform-specific

Next Steps