0Pricing
Kotlin Academy · Lekcja

Wstrzykiwanie zależności w KMP za pomocą Koin

Połącz współdzielone moduły za pomocą Koin w konfiguracji wieloplatformowej.

Wstrzykiwanie zależności w KMP za pomocą Koin to bezpłatna lekcja Kotlin Academy na CoddyKit. To lekcja 4 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Kotlin Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Kotlin Academy zawiera 4 lekcji w sumie.

Dlaczego DI w KMP?

Wstrzykiwanie zależności oddziela tworzenie komponentów od ich używania. W KMP Koin jest najczęściej wybieranym frameworkiem DI, ponieważ został napisany w czystym Kotlinie i działa w commonMain bez procesorów adnotacji.

// 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 modułów Koin

Zdefiniuj powiązania w bloku module { }, używając elementów single, factory lub 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
}

Współdzielony moduł w commonMain

Zdefiniuj współdzielony moduł Koin w commonMain. Moduły platformowe rozszerzają go o powiązania specyficzne dla platformy.

// commonMain/di/SharedModule.kt
import org.koin.dsl.module
fun sharedModule() = module {
    single<UserRepository> { RemoteUserRepository(get()) }
    single { GetUserUseCase(get()) }
    single { UserViewModel(get()) }
}

Moduł platformowy w androidMain

Moduły platformowe dostarczają rzeczywisty silnik HTTP, sterownik bazy danych i singletony specyficzne dla Androida.

// 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())
}

startKoin w aplikacji Android

Wywołaj startKoin { } w metodzie Application.onCreate aplikacji Android. Użyj androidContext(this), aby udostępnić kontekst.

// androidMain:
import org.koin.android.ext.koin.androidContext
import org.koin.core.context.startKoin
// In Application.onCreate():
startKoin {
    androidContext(this@MyApp)
    modules(androidModule())
}

Uruchamianie Koin na iOS

Na iOS wywołaj KoinApplication.start() z poziomu struktury Swift AppDelegate lub App, przekazując współdzielone moduły Koin.

// iosMain/KoinInit.kt:
import org.koin.core.context.startKoin
fun initKoin() {
    startKoin {
        modules(iosModule())
    }
}
// Swift: KoinInitKt.doInitKoin() in AppDelegate

Rozwiązywanie zależności

W ViewModelach lub przypadkach użycia w commonMain używaj get() wewnątrz modułu albo inject() / getKoin().get() w miejscach wywołania.

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) }
}

Zakresy Koin dla ViewModeli

Używaj viewModel { } w module Android dla ViewModeli Androida albo niezależnego od platformy elementu factory { } dla współdzielonych ViewModeli.

// androidMain (with koin-android):
import org.koin.androidx.viewmodel.dsl.viewModel
val androidVmModule = module {
    viewModel { UserViewModel(get()) }
}
// In Compose:
// val vm: UserViewModel = koinViewModel()

Testowanie z Koin

Użyj startKoin w konfiguracji testów wraz z modułem testowym, który zastępuje rzeczywiste zależności fałszywymi implementacjami.

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()
}

single vs factory vs scoped

single: jedna instancja przez cały czas działania aplikacji. factory: nowa instancja przy każdym wywołaniu get(). scoped: jedna instancja na zakres Koin (np. zakres ekranu).

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 vs ręczne DI vs Hilt

Koin: wieloplatformowy, bez KSP/KAPT, DI w czasie działania. Hilt: tylko Android, działanie w czasie kompilacji, obsługa za pomocą adnotacji. Ręczne DI: maksymalna kontrola, brak narzutu frameworka. Projekty KMP używają Koin do współdzielenia kodu.

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")
}

Leniwe wstrzykiwanie za pomocą by inject()

by inject() leniwie rozwiązuje zależność przy pierwszym dostępie — jest przydatne w klasach implementujących 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)
}

Szybkie sprawdzenie

Zakres Koin którego typu tworzy nową instancję przy każdym wywołaniu get()?

Podsumowanie

Koin używa DSL opartego na lambdach i nie wymaga przetwarzania adnotacji — idealnie nadaje się do KMP. Zdefiniuj współdzielone moduły w commonMain, a moduły platformowe w zestawach źródeł platformy. Używaj single dla singletonów, factory dla nowych instancji oraz by inject() do leniwego rozwiązywania zależności.

Często zadawane pytania

Czy lekcja „Wstrzykiwanie zależności w KMP za pomocą Koin” jest bezpłatna?

Tak — pełny tekst „Wstrzykiwanie zależności w KMP za pomocą Koin” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Kotlin Academy, przejdź na CoddyKit PRO. Kurs Kotlin Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Wstrzykiwanie zależności w KMP za pomocą Koin”?

Połącz współdzielone moduły za pomocą Koin w konfiguracji wieloplatformowej. Ćwiczysz Kotlin Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć Kotlin Academy?

Nie wymagamy żadnego doświadczenia. Kotlin Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 4 z 4.

Ile czasu zajmuje lekcja „Wstrzykiwanie zależności w KMP za pomocą Koin”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji Kotlin Academy?

Tak. Każda lekcja Kotlin Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Struktura projektu KMP: commonMain, androidMain, iosMain
  2. Mechanizm expect/actual dla API platform
  3. Współdzielenie warstw Repository i Use Case
  4. Wstrzykiwanie zależności w KMP za pomocą Koin
← Powrót do Kotlin Academy