Kotlin Academy · Урок

Внедрение зависимостей в KMP с Koin

Связывайте общие модули с помощью Koin в мультиплатформенной конфигурации.

Урок 4 из 414 шагов

«Внедрение зависимостей в 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 — локальная установка не требуется.

Все уроки этого курса

  1. Структура проекта KMP: commonMain, androidMain, iosMain
  2. Механизм expect/actual для API платформ
  3. Общие слои репозитория и вариантов использования
  4. Внедрение зависимостей в KMP с Koin
← Назад к Kotlin Academy