Внедрение зависимостей в KMP с Koin
Связывайте общие модули с помощью Koin в мультиплатформенной конфигурации.
«Внедрение зависимостей в KMP с Koin» — бесплатный урок Kotlin Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Kotlin Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Kotlin Academy содержит 4 уроков всего.
Зачем нужен DI в KMP?
Внедрение зависимостей отделяет создание компонентов от их использования. В KMP основным фреймворком DI является Koin, поскольку это чистый Kotlin, работающий в commonMain без процессоров аннотаций.
// No annotation processing needed — Koin uses lambda DSL
// Add to build.gradle.kts:
// implementation("io.insert-koin:koin-core:3.5.0")
// androidMain: koin-android
// iosMain: no extra dep
fun main() { println("Koin works on all KMP targets") }DSL модулей Koin
Определяйте привязки в блоке module { }, используя single, factory или scoped.
import org.koin.core.module.dsl.*
import org.koin.dsl.*
val appModule = module {
single { HttpClient() } // one instance
single<UserRepository> { RemoteUserRepository(get()) }
factory { GetUserUseCase(get()) } // new instance each time
}Общий модуль в commonMain
Определите общий модуль Koin в commonMain. Платформенные модули расширяют его платформенными привязками.
// commonMain/di/SharedModule.kt
import org.koin.dsl.module
fun sharedModule() = module {
single<UserRepository> { RemoteUserRepository(get()) }
single { GetUserUseCase(get()) }
single { UserViewModel(get()) }
}Платформенный модуль в androidMain
Платформенные модули предоставляют фактический HTTP-движок, драйвер базы данных и одиночные объекты, специфичные для Android.
// androidMain/di/AndroidModule.kt
import io.ktor.client.engine.okhttp.*
import org.koin.dsl.module
fun androidModule() = module {
single { OkHttp.create() } // Ktor engine
single { createHttpClient(get()) }
includes(sharedModule())
}Запуск Koin в приложении Android
Вызовите startKoin { } в Application.onCreate приложения Android. Используйте androidContext(this), чтобы сделать контекст доступным.
// androidMain:
import org.koin.android.ext.koin.androidContext
import org.koin.core.context.startKoin
// In Application.onCreate():
startKoin {
androidContext(this@MyApp)
modules(androidModule())
}Запуск Koin на iOS
В iOS вызовите KoinApplication.start() из Swift-кода AppDelegate или структуры App, передав общие модули Koin.
// iosMain/KoinInit.kt:
import org.koin.core.context.startKoin
fun initKoin() {
startKoin {
modules(iosModule())
}
}
// Swift: KoinInitKt.doInitKoin() in AppDelegateРазрешение зависимостей
В ViewModels или сценариях использования в commonMain используйте get() внутри модуля либо inject() / getKoin().get() в местах вызова.
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject
class UserViewModel : KoinComponent {
private val getUser: GetUserUseCase by inject()
fun load(id: String) = runBlocking { getUser(id) }
}Области действия Koin для ViewModels
Используйте viewModel { } в модуле Android для ViewModels Android или независимый от платформы factory { } для общих VM.
// androidMain (with koin-android):
import org.koin.androidx.viewmodel.dsl.viewModel
val androidVmModule = module {
viewModel { UserViewModel(get()) }
}
// In Compose:
// val vm: UserViewModel = koinViewModel()Тестирование с Koin
Используйте startKoin при настройке тестов вместе с тестовым модулем, который заменяет реальные зависимости фиктивными.
import org.koin.core.context.startKoin
import org.koin.core.context.stopKoin
import org.koin.dsl.module
class UserViewModelTest {
@BeforeTest fun setup() {
startKoin { modules(module {
single<UserRepository> { FakeUserRepository() }
single { GetUserUseCase(get()) }
})}
}
@AfterTest fun teardown() = stopKoin()
}Одиночный объект, фабрика или область действия
Одиночный объект: один экземпляр на всё время работы приложения. Фабрика: новый экземпляр при каждом вызове get(). Ограниченная область действия: один экземпляр на область действия Koin, например область действия экрана.
import org.koin.dsl.module
val lifetimeModule = module {
single { Database() } // shared, one instance
factory { Analytics() } // new on each get()
scope<ScreenScope> {
scoped { ScreenViewModel() } // one per screen lifecycle
}
}Koin, ручное DI или Hilt
Koin: мультиплатформенность, отсутствие KSP/KAPT и внедрение зависимостей во время выполнения. Hilt: только Android, внедрение во время компиляции на основе аннотаций. Ручное DI: максимальный контроль без накладных расходов фреймворка. В проектах KMP для общего кода используют Koin.
fun main() {
// Koin : commonMain, runtime, lambda DSL
// Hilt : androidMain only, compile-time
// Manual: no framework, explicit wiring in factory/module files
println("Choose Koin for KMP; Hilt for Android-only projects")
}Ленивая инъекция
by inject() разрешает зависимость при первом обращении, что удобно в классах, реализующих KoinComponent.
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject
class AppService : KoinComponent {
private val repo: UserRepository by inject() // resolved on first use
fun doWork() = println(repo.javaClass.simpleName)
}Быстрая проверка
Какая область действия Koin создаёт новый экземпляр при каждом вызове get()?
Итоги
Koin использует лямбда-DSL без обработки аннотаций, что идеально подходит для KMP. Определяйте общие модули в commonMain, а платформенные модули — в наборах исходного кода платформ. Используйте single для одиночных объектов, factory для новых экземпляров и by inject() для ленивого разрешения зависимостей.
Изучай Kotlin с ИИ-репетитором — бесплатно
Пиши и запускай код прямо в браузере, получай мгновенную помощь от ИИ-репетитора 24/7 и продолжи учиться на сайте или в приложении.
- Курсы
- 51
- Уроки
- 203
Часто задаваемые вопросы
Урок «Внедрение зависимостей в KMP с Koin» бесплатный?
Да — полный текст урока «Внедрение зависимостей в KMP с Koin» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Kotlin Academy, подпишись на CoddyKit PRO. Курс Kotlin Academy содержит 4 уроков всего.
Чему я научусь в уроке «Внедрение зависимостей в KMP с Koin»?
Связывайте общие модули с помощью Koin в мультиплатформенной конфигурации. Ты практикуешь Kotlin Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Kotlin Academy?
Предыдущий опыт не требуется. Kotlin Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.
Сколько времени занимает урок «Внедрение зависимостей в KMP с Koin»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Kotlin Academy?
Да. Каждый урок Kotlin Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Структура проекта KMP: commonMain, androidMain, iosMain
- Механизм expect/actual для API платформ
- Общие слои репозитория и вариантов использования
- Внедрение зависимостей в KMP с Koin