Koin je DI framework pro Kotlin, který pracuje bez generování kódu, reflexe a anotací. Knihovna používá DSL pro popis modulů a vkládá závisnosti přes lehký kontejner s podporou Android, Ktor a Multiplatform. Podle oficiální dokumentace Koin, framework poskytuje moduly, scope a vestavěnou podporu Jetpack Compose s minimálním boilerplate.
Hlavní body
Koin — DI framework pro Kotlin, napsaný v čistém jazyce bez použití reflexe, anotací nebo generování kódu. Na rozdíl od Dagger Hilt, který vyžaduje procesor anotací a generování kódu při kompilaci, Koin pracuje výhradně v runtime pomocí lehkého DSL pro popis modulů.
Hlavní myšlenkou Koin je poskytnout jednoduché API pro registraci a řešení závislostí bez nutnosti učit se složité koncepty grafů závislostí a stromů komponent. Vývojář popíše, které třídy jsou k dispozici kontejneru, a Koin je automaticky vkládá přes konstruktor nebo líné delegáty by inject. Framework je plně kompatibilní s Kotlin Multiplatform, což umožňuje jednotný DI přístup na Android, iOS a serverové straně.
Podle průzkumu Kotlin Developers Community (2025) je Koin používán v 31% komerčních Android projektů, v popularitě zaostává pouze za Hilt (47%). Hlavní důvod výběru — jednoduchost konfigurace a absence potřeby generování kódu, což urychluje sestavení projektu.
Vyberte Koin pro střední a velké projekty, kde je důležitý rychlý start vývoje, nebo pro Kotlin Multiplatform řešení, kde Hilt není k dispozici z architektonických důvodů.
Koin nepoužívá reflexi a generování kódu — všechny registrace jsou založeny na inline funkcích s reified typy, které při kompilaci dosazují konkrétní typ do těla funkce. To dělá Koin jedním z nejlehčích DI frameworků co do velikosti výsledného APK: přidání Koin zvyšuje velikost aplikace pouze o 100–150 KB, zatímco Dagger Hilt přidává přibližně 500 KB kvůli generovanému kódu.
Kontejner Koin je inicializován pomocí funkce startKoin, která přijímá lambdu s konfigurací. Uvnitř této lambdy jsou popsány moduly s registracemi — hlavní stavební blok DI logiky.
Funkce startKoin vytváří globální kontejner přístupný z libovolného místa aplikace přes GlobalContext, ale v multimodulových projektech se doporučuje použít KoinApplication pro vytvoření izolovaných kontejnerů. V Androidu se pro inicializaci používá AndroidContext, který se automaticky váže k životnímu cyklu Application. Moduly jsou registrovány přes parametr modules, který přijímá seznam instancí Module.
val networkModule = module {
single {
OkHttpClient()
}
single {
Retrofit.Builder()
.baseUrl("https://api.example.com")
.build()
}
}
startKoin {
modules(networkModule)
}
Každý modul obsahuje definice přes single (singleton) nebo factory (nová instance). Definice mohou odkazovat na jiné registrované závislosti přes get(), což tvoří graf vkládání bez explicitního určování typů a bez boilerplate kódu.
Koin aktivně používá inline funkce s reified parametry pro odvození typu z kontextu. To umožňuje psát registrace bez explicitního určení třídy: single { MyService() } automaticky určí typ podle návratové hodnoty lambdy.
Na rozdíl od Dagger, Koin nekontroluje graf závislostí při kompilaci — všechny chyby jsou detekovány v runtime při prvním přístupu k nevyřešené závislosti. To je kompromis, který výrazně zjednodušuje kód a urychluje sestavení, ale vyžaduje testovací pokrytí DI konfigurace.
Ve verzi Koin 3.5 se objevila experimentální kontrola grafu při kompilaci přes plugin Koin Annotations. Hlavní výhoda Koin — absence generování kódu — se však v tomto režimu ztrácí, proto většina týmů nadále používá klasický DSL přístup s runtime kontrolami pomocí testů.
Koin poskytuje několik způsobů vkládání závislostí: by inject(), get() a přímé předání přes konstruktor. Výběr způsobu závisí na kontextu použití.
Delegát by inject — nejběžnější způsob vkládání ve ViewModel a Android fragmentech. Závislost je inicializována líně — pouze při prvním přístupu k vlastnosti.
class MainViewModel : ViewModel() {
private val repository: UserRepository by inject()
fun loadUsers() {
repository.fetchAll()
}
}
Funkce get vrací instanci závislosti okamžitě. Na rozdíl od by inject(), get() nepodporuje líné načítání a vyžaduje, aby kontejner byl již inicializován v okamžiku volání.
Scope v Koin — mechanismus vázání životnosti závislostí na konkrétní komponent, jako je Activity, Fragment nebo uživatelská relace.
Funkce scope uvnitř modulu vytváří scope, který žije tak dlouho, dokud žije připojený komponent. Všechny závislosti registrované v scopu jsou zničeny při jeho uzavření, což zabraňuje únikům paměti.
val userScope = module {
scope<UserSession> {
scoped {
UserRepository(get())
}
scoped {
SessionManager(get())
}
}
}
Funkce scoped registruje závislost, která bude existovat pouze uvnitř scopu.
single — registrace jediné instance pro celou aplikaci s línou inicializací. factory — každé volání get() vytváří novou instanci, používá se pro ViewModel, repozitáře a objekty se stavem.
Integrace Koin do Android projektu je minimální: stačí přidat závislost do build.gradle a zavolat startKoin v Application.onCreate. Koin poskytuje moduly pro integraci s Jetpack Compose, Navigation a WorkManager.
Speciální knihovna koin-android-compose umožňuje vkládání závislostí přímo do Composable funkcí přes koinViewModel() a koinInject().
Podle Google I/O 2024 se Jetpack Compose stal hlavním frameworkem pro nové Android projekty. Koin poskytuje nativní podporu Compose bez dodatečné konfigurace.
Pro testování Koin poskytuje funkce koinTest a koinTestRule, které vytvářejí izolovaný testovací kontejner s testovacími moduly. Integrace s Jetpack Navigation se realizuje přes modul koin-androidx-navigation.
Pro unit testování ViewModel s Koin se používá koinTestRule z knihovny koin-test-junit5 nebo koin-test-junit4. Skutečné závislosti jsou nahrazeny mocky přes MockK.
Jednou z klíčových možností Koin 3.x je podpora Ktor pro vytváření serverových aplikací v Kotlin a Compose Multiplatform pro desktopové aplikace. To dělá Koin jediným DI frameworkem pokrývajícím všechny tři platformy Kotlin beze změny injekčního paradigmatu.
Pro multimodulové projekty Koin podporuje líné načítání modulů přes loadKoinModules, což umožňuje nezávislé připojení DI konfigurace každého feature modulu.
Často kladené otázky
Koin pracuje v runtime bez generování kódu a anotací, což urychluje sestavení, ale nekontroluje graf závislostí při kompilaci. Hilt generuje kód při kompilaci a detekuje chyby DI dříve, ale vyžaduje složitou konfiguraci a zpomaluje build.
Ano, Koin plně podporuje Kotlin Multiplatform. Knihovna koin-core funguje na všech platformách Kotlin.
Cyklické závislosti vedou k StackOverflowError v runtime. Koin je neodhaluje automaticky. Řešením je refaktorování architektury.
V Androidu lze scope připojit k životnímu cyklu Activity nebo Fragment přes AndroidScope. Při zničení komponentu Koin automaticky uzavře příslušný scope.
Použijte funkci koinTest z modulu koin-test. Vytvoří izolovaný kontejner s testovacími moduly, který se po testu automaticky uzavře.
Shrnutí
Vyvineme mobilní aplikaci na klíč
IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.
Přečtěte si také