Koin — Dependency Injection Container für Kotlin
In der modernen Kotlin-Entwicklung ist die Verwaltung von Abhängigkeiten eine wichtige Aufgabe. Koin ist ein leichtgewichtiger Dependency Injection (DI) Container, der in Kotlin geschrieben ist und keine Codegenerierung, Reflexion oder komplexe Konfiguration erfordert. Im Gegensatz zu Dagger oder Spring verwendet Koin eine einfache DSL und ist vollständig in Coroutinen und Flow integriert. Auf dieser Seite erklären wir, wie Sie Koin installieren, Module deklarieren, Abhängigkeiten injizieren und es in Bildungsprojekten verwenden.
Was ist Dependency Injection?
Dependency Injection (DI) ist ein Entwurfsmuster, bei dem ein Objekt seine Abhängigkeiten von außen erhält, anstatt sie selbst zu erstellen. Dies vereinfacht das Testen, macht den Code flexibler und verringert die Kopplung. Koin implementiert DI über einen Container, der die Erstellung und den Lebenszyklus von Objekten verwaltet.
Installation von Koin
Fügen Sie die folgende Abhängigkeit in Ihre build.gradle.kts-Datei ein:
// build.gradle.ktsdependencies { implementation("io.insert-koin:koin-core:3.5.3") // Für Android implementation("io.insert-koin:koin-android:3.5.3")}Grundlegende Konzepte von Koin
- Modul (module) — ein Block, in dem Abhängigkeiten deklariert werden.
- Definition (definition) — die Art und Weise, ein Objekt zu erstellen (single, factory, scoped).
- Container (KoinApplication) — startet und verwaltet die Module.
- Injektion (inject) — Abrufen einer Abhängigkeit über Delegaten oder Funktionen.
Module erstellen und Abhängigkeiten deklarieren
Koin verwendet eine DSL zur Beschreibung von Modulen. Betrachten wir ein Beispiel mit einem Repository und einem Service:
// Schnittstelle und Implementierung definiereninterface UserRepository { fun getUser(id: Int): String}
class UserRepositoryImpl : UserRepository { override fun getUser(id: Int) = "User #$id"}
class UserService(private val repository: UserRepository) { fun printUser(id: Int) { println(repository.getUser(id)) }}
// Koin-Modulval appModule = module { // single — erstellt eine einzelne Instanz (Singleton) single<UserRepository> { UserRepositoryImpl() } // factory — erstellt bei jeder Anfrage eine neue Instanz factory { UserService(get()) }}Container starten
Vor der Verwendung von Abhängigkeiten muss Koin gestartet werden:
import org.koin.core.context.startKoin
fun main() { startKoin { modules(appModule) } // Jetzt können Abhängigkeiten abgerufen werden val service: UserService by inject() service.printUser(42)}Methoden der Abhängigkeitsinjektion
- by inject() — verzögerter Abruf (empfohlen).
- get() — sofortiger Abruf.
- Konstruktor — Koin übergibt Abhängigkeiten automatisch an den Konstruktor.
Beispiel mit by inject():
class MyActivity : AppCompatActivity() { // Verzögerte Injektion private val repository: UserRepository by inject() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // repository verwenden }}Scoped-Abhängigkeiten
Manchmal ist es notwendig, eine Abhängigkeit zu erstellen, die innerhalb eines bestimmten Kontexts (z. B. einer Benutzersitzung) lebt. Dafür wird scope verwendet:
val sessionModule = module { scope<UserSession> { scoped { UserSessionManager(get()) } }}Arbeiten mit Coroutinen
Koin unterstützt Coroutinen über das Modul koin-core-coroutines. Beispiel für asynchronen Abruf:
import org.koin.core.component.KoinComponentimport org.koin.core.component.inject