Koin är ett DI-ramverk för Kotlin som fungerar utan kodgenerering, reflektion och annoteringar. Biblioteket använder DSL för att beskriva moduler och injicerar beroenden genom en lätt container med stöd för Android, Ktor och Multiplatform. Enligt Koin officiella dokumentation tillhandahåller ramverket moduler, scopes och inbyggt stöd för Jetpack Compose med minimal boilerplate.
Huvudpunkter
Koin — DI-ramverk för Kotlin, skrivet i rent språk utan användning av reflektion, annoteringar eller kodgenerering. Till skillnad från Dagger Hilt, som kräver en annoteringsprocessor och kodgenerering vid kompilering, fungerar Koin uteslutande vid körning med hjälp av ett lätt DSL för att beskriva moduler.
Huvudidén med Koin är att tillhandahålla ett enkelt API för registrering och upplösning av beroenden utan att behöva lära sig komplexa begrepp som beroendegrafer och komponentträd. Utvecklaren beskriver vilka klasser som är tillgängliga för containern, och Koin injicerar dem automatiskt via konstruktorn eller lata by inject-delegater. Ramverket är fullt kompatibelt med Kotlin Multiplatform, vilket möjliggör en enhetlig DI-metod på Android, iOS och serversidan.
Enligt Kotlin Developers Community-enkäten (2025) används Koin i 31% av kommersiella Android-projekt, och det är bara Hilt (47%) som är mer populärt. Huvudorsaken till valet är enkelheten i konfigurationen och avsaknaden av behov av kodgenerering, vilket snabbar upp projektbygget.
Välj Koin för medelstora och stora projekt där en snabb utvecklingsstart är viktig, eller för Kotlin Multiplatform-lösningar där Hilt inte är tillgängligt av arkitektoniska skäl.
Koin använder inte reflektion och kodgenerering — alla registreringar baseras på inline-funktioner med reified-typer som vid kompilering ersätter den konkreta typen i funktionskroppen. Detta gör Koin till ett av de lättaste DI-ramverken när det gäller slutlig APK-storlek: att lägga till Koin ökar appstorleken med endast 100–150 KB, medan Dagger Hilt lägger till cirka 500 KB på grund av genererad kod.
Koin-containern Koin initieras via funktionen startKoin som tar emot en lambda med konfiguration. Inuti denna lambda beskrivs moduler med registreringar — den primära byggstenen för DI-logik.
Funktionen startKoin skapar en global container som är tillgänglig från vilken punkt som helst i applikationen via GlobalContext, men i multimodulprojekt rekommenderas att använda KoinApplication för att skapa isolerade containrar. I Android används AndroidContext för initiering, som automatiskt binds till Application livscykel. Moduler registreras via parametern modules som tar emot en lista av Module-instanser.
val networkModule = module {
single {
OkHttpClient()
}
single {
Retrofit.Builder()
.baseUrl("https://api.example.com")
.build()
}
}
startKoin {
modules(networkModule)
}
Varje modul innehåller definitioner via single (singleton) eller factory (ny instans). Definitioner kan referera till andra registrerade beroenden via get(), vilket bildar en injektionsgraf utan explicit typangivelse och utan boilerplate-kod.
Koin använder aktivt inline-funktioner med reified-parametrar för att härleda typ från kontexten. Detta gör det möjligt att skriva registreringar utan explicit klassangivelse: single { MyService() } bestämmer automatiskt typen baserat på lambdans returvärde.
Till skillnad från Dagger kontrollerar Koin inte beroendegrafen vid kompilering — alla fel upptäcks vid körning vid första åtkomst till ett olöst beroende. Detta är en kompromiss som avsevärt förenklar koden och snabbar upp bygget, men kräver testtäckning av DI-konfigurationen.
I Koin version 3.5 introducerades experimentell grafkontroll vid kompilering via Koin Annotations-plugin. Huvudfördelen med Koin — avsaknad av kodgenerering — går dock förlorad i detta läge, så de flesta team fortsätter att använda den klassiska DSL-metoden med körningskontroller via tester.
Koin erbjuder flera sätt att injicera beroenden: by inject(), get() och direkt överföring via konstruktorn. Valet av metod beror på användningskontexten.
Delegaten by inject — den vanligaste injektionsmetoden i ViewModel och Android-fragment. Beroendet initieras lätt — endast vid första åtkomst till egenskapen.
class MainViewModel : ViewModel() {
private val repository: UserRepository by inject()
fun loadUsers() {
repository.fetchAll()
}
}
Funktionen get returnerar omedelbart instansen av beroendet. Till skillnad från by inject() stöder get() inte lat laddning och kräver att containern redan är initierad vid anropstillfället.
Scope i Koin — mekanism för att binda beroendens livslängd till en specifik komponent, såsom Activity, Fragment eller användarsession.
Funktionen scope inuti en modul skapar ett scope som lever så länge den kopplade komponenten lever. Alla beroenden som registrerats i scopet förstörs när det stängs, vilket förhindrar minnesläckor.
val userScope = module {
scope<UserSession> {
scoped {
UserRepository(get())
}
scoped {
SessionManager(get())
}
}
}
Funktionen scoped registrerar ett beroende som endast kommer att existera inom scopet.
single — registrering av en enda instans för hela applikationen med lat initiering. factory — varje get()-anrop skapar en ny instans, används för ViewModel, repositories och objekt med tillstånd.
Integration av Koin i ett Android-projekt är minimal: lägg till beroendet i build.gradle och anropa startKoin i Application.onCreate. Koin tillhandahåller moduler för integration med Jetpack Compose, Navigation och WorkManager.
Det speciella biblioteket koin-android-compose möjliggör direkt injektion av beroenden i Composable-funktioner via koinViewModel() och koinInject().
Enligt Google I/O 2024 har Jetpack Compose blivit det primära ramverket för nya Android-projekt. Koin ger native Compose-stöd utan extra konfiguration.
För testning tillhandahåller Koin funktionerna koinTest och koinTestRule som skapar en isolerad testcontainer med testmoduler. Integration med Jetpack Navigation sker via modulen koin-androidx-navigation.
För enhetstestning av ViewModel med Koin används koinTestRule från biblioteket koin-test-junit5 eller koin-test-junit4. Verkliga beroenden ersätts med mockar via MockK.
En av nyckelfunktionerna i Koin 3.x är stöd för Ktor för att skapa serverapplikationer i Kotlin och Compose Multiplatform för skrivbordsapplikationer. Detta gör Koin till det enda DI-ramverk som täcker alla tre Kotlin-plattformar utan att ändra injektionsparadigm.
För multimodulprojekt stöder Koin lat inläsning av moduler via loadKoinModules, vilket möjliggör oberoende anslutning av DI-konfigurationen för varje feature-modul.
Vanliga frågor
Koin fungerar vid körning utan kodgenerering och annoteringar, vilket snabbar upp bygget, men kontrollerar inte beroendegrafen vid kompilering. Hilt genererar kod vid kompilering och upptäcker DI-fel tidigare, men kräver komplex konfiguration och saktar ner bygget.
Ja, Koin stöder fullt ut Kotlin Multiplatform. Biblioteket koin-core fungerar på alla Kotlin-plattformar.
Cykliska beroenden leder till StackOverflowError vid körning. Koin upptäcker dem inte automatiskt. Lösningen är arkitekturrefaktorering.
I Android kan scopes kopplas till Activity eller Fragment livscykel via AndroidScope. När komponenten förstörs stänger Koin automatiskt motsvarande scope.
Använd funktionen koinTest från modulen koin-test. Den skapar en isolerad container med testmoduler som automatiskt stängs efter testet.
Sammanfattning
Vi utvecklar en mobil applikation nyckelfärdigt
IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.
Läs också