Step 5 of 7
Koin for KMP, module definitions in commonMain, platform initialization
Koin สำหรับ KMP — module definitions ใน commonMain, platform-specific modules
Koin is a pragmatic dependency injection (DI) framework with no code generation and no reflection. It runs on common code. You define modules once and start them on each platform.
Version: Koin 4.x.
// shared/build.gradle.kts
kotlin {
sourceSets {
commonMain.dependencies {
implementation("io.insert-koin:koin-core:4.0.0")
implementation("io.insert-koin:koin-compose:4.0.0")
implementation("io.insert-koin:koin-compose-viewmodel:4.0.0")
implementation("org.jetbrains.androidx.lifecycle:lifecycle-viewmodel-compose:2.9.4")
}
androidMain.dependencies {
implementation("io.insert-koin:koin-android:4.0.0")
}
}
}
koin-compose-viewmodel gives you a multiplatform ViewModel and the viewModelOf DSL.
// commonMain
import org.koin.core.module.dsl.singleOf
import org.koin.core.module.dsl.viewModelOf
import org.koin.dsl.module
val appModule = module {
singleOf(::PostApi) // from the networking lesson
singleOf(::UserRepository) // from the SQLDelight lesson
viewModelOf(::PostViewModel)
}
singleOf creates one shared instance. viewModelOf creates a ViewModel tied to the UI lifecycle.
// commonMain
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
class PostViewModel(
private val repo: UserRepository,
) : ViewModel() {
private val _users = MutableStateFlow<List<String>>(emptyList())
val users: StateFlow<List<String>> = _users
fun load() {
viewModelScope.launch {
_users.value = repo.all().map { it.name }
}
}
}
// androidMain
import org.koin.core.context.startKoin
class MyApp : android.app.Application() {
override fun onCreate() {
super.onCreate()
startKoin {
modules(appModule)
}
}
}
Register MyApp in AndroidManifest.xml with android:name=".MyApp".
Start Koin once, then the Swift side calls shared code.
// commonMain
import org.koin.core.context.startKoin
fun initKoin() {
startKoin { modules(appModule) }
}
// iosApp (Swift)
initKoin()
// commonMain
import org.koin.compose.viewmodel.koinViewModel
@Composable
fun UserScreen(viewModel: PostViewModel = koinViewModel()) {
val users by viewModel.users.collectAsState()
LaunchedEffect(Unit) { viewModel.load() }
users.forEach { Text(it) }
}
Diagram: commonMain defines modules and a ViewModel; each platform starts Koin; the Compose UI injects via Koin.
Loading diagram...
Alice
Bob
koin-core and koin-compose to a shared module.singleOf(::UserRepository) and viewModelOf(::PostViewModel).Application class.PostViewModel in a Composable using koinViewModel() and show the user list.