Kotlin Academy · Lektion

Dependency injection i KMP med Koin

Koppla samman delade moduler med Koin i en multiplattformsuppsättning.

Lektion 4 av 414 steg

Dependency injection i KMP med Koin är en gratis lektion i Kotlin Academy på CoddyKit. Detta är lektion 4 av 4. Du kan läsa vilka 3 lektioner som helst i den här lärvägen kostnadsfritt i sin helhet – därefter låser CoddyKit PRO upp alla lektioner, plus praktisk övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Den ingår i lärvägen för Kotlin Academy, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i Kotlin Academy innehåller totalt 4 lektioner.

Varför DI i KMP?

Dependency Injection kopplar loss skapandet av komponenter från användningen av dem. I KMP är Koin det självklara DI-ramverket eftersom det består av ren Kotlin-kod och fungerar i commonMain utan annoteringsprocessorer.

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

Koin-modulens DSL

Definiera bindningar i ett module { }-block med hjälp av single, factory eller 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
}

Delad modul i commonMain

Definiera en delad Koin-modul i commonMain. Plattformarnas moduler utökar den med plattformsspecifika bindningar.

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

Plattformsmodul i androidMain

Plattformsmoduler tillhandahåller den faktiska HTTP-motorn, databasenhetsdrivrutinen och Android-specifika singleton-instansieringar.

// 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 i Android Application

Anropa startKoin { } i din Android-Application.onCreate. Använd androidContext(this) för att göra kontexten tillgänglig.

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

Starta Koin på iOS

På iOS anropar du KoinApplication.start() från din Swift-AppDelegate eller App-struct och skickar med de delade Koin-modulerna.

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

Slå upp beroenden

I ViewModels eller use cases i commonMain använder du get() inuti en modul eller inject() / getKoin().get() på anropsplatserna.

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-scope för ViewModels

Använd viewModel { } i Android-modulen för Android-ViewModels eller den plattformsoberoende factory { } för delade ViewModels.

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

Testning med Koin

Använd startKoin i testkonfigurationen med en testmodul som ersätter verkliga beroenden med fejkade implementationer.

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 kontra Factory kontra Scoped

single: en instans under appens livstid. factory: en ny instans per anrop till get(). scoped: en instans per Koin-scope (till exempel ett skärmscope).

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 kontra manuell DI kontra Hilt

Koin: multiplattform, ingen KSP/KAPT, DI vid körning. Hilt: endast Android, vid kompilering och annoteringsdrivet. Manuell DI: maximal kontroll utan ramverkskostnad. KMP-projekt använder Koin för att dela kod.

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

Lazy injection med by inject()

by inject() slår upp ett beroende först när det används – praktiskt i klasser som implementerar 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)
}

Snabbkontroll

Vilket Koin-scope skapar en ny instans varje gång get() anropas?

Sammanfattning

Koin använder en lambda-DSL utan annoteringsbehandling – idealiskt för KMP. Definiera delade moduler i commonMain och plattformsmoduler i plattformarnas source sets. Använd single för singleton-instansieringar, factory för nya instanser och by inject() för lazy upplösning.

Gratis att börja

Lär dig Kotlin med en AI-lärare – gratis

Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.

Kurser
51
Lektioner
203

Vanliga frågor

Är lektionen ”Dependency injection i KMP med Koin” gratis?

Ja – du kan läsa vilka 3 lektioner som helst i lärvägen Kotlin Academy, inklusive ”Dependency injection i KMP med Koin”, kostnadsfritt i sin helhet här på webben. Därefter låser CoddyKit PRO upp alla lektioner, plus interaktiv övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Kursen i Kotlin Academy innehåller totalt 4 lektioner.

Vad lär jag mig i ”Dependency injection i KMP med Koin”?

Koppla samman delade moduler med Koin i en multiplattformsuppsättning. Ni övar på Kotlin Academy med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.

Behöver jag någon erfarenhet för att börja lära mig Kotlin Academy?

Du behöver inga förkunskaper. Utbildningen i Kotlin Academy på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 4 av 4.

Hur lång tid tar lektionen ”Dependency injection i KMP med Koin”?

De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.

Kan jag skriva och köra kod i den här Kotlin Academy-lektionen?

Ja. Varje Kotlin Academy-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.

Alla lektioner i den här kursen

  1. KMP-projektstruktur: commonMain, androidMain, iosMain
  2. expect/actual-mekanismen för plattforms-API:er
  3. Dela repository- och use case-lager
  4. Dependency injection i KMP med Koin
← Tillbaka till Kotlin Academy