Koin, kod üretimi, yansıma veya ek açıklama olmadan çalışan bir Kotlin DI framework'üdür. Kütüphane, modülleri tanımlamak için DSL kullanır ve Android, Ktor ve Multiplatform desteğiyle hafif bir konteyner aracılığıyla bağımlılıkları enjekte eder. Resmi Koin dokümantasyonuna göre, framework, minimum boilerplate ile modüller, kapsamlar ve Jetpack Compose için yerleşik destek sağlar.
Önemli Noktalar
Koin, yansıma, ek açıklama veya kod üretimi kullanmadan saf dille yazılmış bir Kotlin DI framework'üdür. Derleme zamanında ek açıklama işlemcisi ve kod üretimi gerektiren Dagger Hilt'in aksine Koin, modülleri tanımlamak için hafif bir DSL kullanarak tamamen çalışma zamanında çalışır.
Koin'in ana fikri, karmaşık bağımlılık grafiği ve bileşen ağacı kavramlarını öğrenmeye gerek kalmadan bağımlılıkları kaydetmek ve çözmek için basit bir API sağlamaktır. Geliştirici, konteyner için hangi sınıfların kullanılabilir olduğunu tanımlar ve Koin, bunları kurucu veya by inject yoluyla tembel temsilciler aracılığıyla otomatik olarak enjekte eder. Framework, Kotlin Multiplatform ile tam uyumludur ve Android, iOS ve sunucu tarafında birleşik bir DI yaklaşımına olanak tanır.
Kotlin Geliştirici Topluluğu anketine (2025) göre Koin, ticari Android projelerinin %31'inde kullanılmakta olup yalnızca Hilt'in (%47) ardından ikinci sıradadır. Seçilmesinin ana nedeni, kurulum kolaylığı ve proje derlemesini hızlandıran kod üretimi gereksiniminin olmamasıdır.
Hızlı geliştirme başlatmanın önemli olduğu orta ve büyük projeler için veya mimari nedenlerle Hilt'in kullanılamadığı Kotlin Multiplatform çözümleri için Koin'i seçin.
Koin, yansıma veya kod üretimi kullanmaz — tüm kayıtlar, derleme zamanında işlev gövdesine somut türü yerleştiren reified türlere sahip inline işlevler üzerine kurulmuştur. Bu, Koin'i nihai APK boyutu açısından en hafif DI framework'lerinden biri yapar: Koin eklemek, uygulama boyutunu yalnızca 100-150 KB artırırken, Dagger Hilt üretilen kod nedeniyle yaklaşık 500 KB ekler.
Koin konteyneri, yapılandırmayla bir lambda alan startKoin işlevi aracılığıyla başlatılır. Bu lambda içinde, DI mantığının ana yapı taşı olan kayıtlı modüller tanımlanır.
startKoin işlevi, GlobalContext aracılığıyla uygulamanın her yerinden erişilebilen küresel bir konteyner oluşturur, ancak çok modüllü projelerde izole konteynerler oluşturmak için KoinApplication kullanılması önerilir. Android'de, başlatma için otomatik olarak Application yaşam döngüsüne bağlanan AndroidContext kullanılır. Modüller, Module örneklerinin bir listesini alan modules parametresi aracılığıyla kaydedilir.
val networkModule = module {
single {
OkHttpClient()
}
single {
Retrofit.Builder()
.baseUrl("https://api.example.com")
.build()
}
}
startKoin {
modules(networkModule)
}
Her modül, single (singleton) veya factory (yeni örnek) aracılığıyla tanımlar içerir. Tanımlar, get() aracılığıyla diğer kayıtlı bağımlılıklara başvurabilir ve açık tür belirtimi ve boilerplate kodu olmadan bir enjeksiyon grafiği oluşturur.
Koin, bağlamdan tür çıkarımı için reified parametrelere sahip inline işlevleri aktif olarak kullanır. Bu, sınıfı açıkça belirtmeden kayıt yazmaya olanak tanır: single { MyService() }, lambda'nın dönüş değerinden türü otomatik olarak belirler.
Dagger'dan farklı olarak Koin, bağımlılık grafiğini derleme zamanında kontrol etmez — tüm hatalar, çözülmemiş bir bağımlılığa ilk erişimde çalışma zamanında tespit edilir. Bu, kodu önemli ölçüde basitleştiren ve derlemeleri hızlandıran ancak DI yapılandırmasının test kapsamını gerektiren bir ödünleşmedir. Birçok ekip, derleme zamanı kontrollerinin olmamasına rağmen, geliştirme hızı ve basitlik için Koin'i seçer.
Koin sürüm 3.5'te, Koin Annotations eklentisi aracılığıyla deneysel derleme zamanı grafik kontrolü ortaya çıktı. Geliştirici @Module ve @KoinComponent ek açıklamalarını ekler ve eklenti, derleme sırasında çalışan doğrulama kodu üretir. Ancak Koin'in ana avantajı — kod üretimi olmaması — bu modda kaybolur, bu nedenle çoğu ekip, testler aracılığıyla çalışma zamanı kontrolleriyle klasik DSL yaklaşımını kullanmaya devam eder.
Koin, bağımlılıkları enjekte etmek için çeşitli yöntemler sunar: by inject(), get() ve doğrudan kurucu aktarımı. Seçim, kullanım bağlamına bağlıdır.
by inject temsilcisi, Android ViewModel ve fragment'larında en yaygın enjeksiyon yöntemidir. Bağımlılık, tembel olarak — yalnızca ilk özellik erişiminde başlatılır. Bu, hemen ihtiyaç duyulmayabilecek kaynak yoğun hizmetler için verimlidir.
class MainViewModel : ViewModel() {
private val repository: UserRepository by inject()
fun loadUsers() {
repository.fetchAll()
}
}
get işlevi, bir bağımlılık örneğini hemen döndürür. Kayıt sırasında fabrika lambdaları içinde veya bağımlılığın tembel başlatma olmadan senkron bir bağlamda gerekli olduğunda kullanılır. by inject()'in aksine, get() tembel yüklemeyi desteklemez ve çağrı sırasında konteynerin zaten başlatılmış olmasını gerektirir.
Koin'de kapsam, bağımlılık yaşam süresini bir Activity, Fragment veya özel oturum gibi belirli bir bileşene bağlama mekanizmasıdır. Bu, Android uygulamalarında bellek yönetimi için anahtar bir işlevdir.
Bir modül içindeki scope işlevi, bağlı bileşen yaşadığı sürece yaşayan bir kapsam oluşturur. Kapsamda kayıtlı tüm bağımlılıklar, kapsam kapatıldığında yok edilir ve bellek sızıntıları önlenir.
val userScope = module {
scope<UserSession> {
scoped {
UserRepository(get())
}
scoped {
SessionManager(get())
}
}
}
scoped işlevi, yalnızca kapsam içinde var olacak bir bağımlılık kaydeder. Kapsam kapatıldığında, tüm scoped nesneler çöp toplayıcı için kullanılabilir hale gelir.
single, tembel başlatma ile tüm uygulama için tek bir örnek kaydeder. Durumsuz hizmetler için kullanılır: ağ istemcileri, önbellekler, günlükçüler.
factory, her get() çağrısında yeni bir örnek oluşturur. Her erişimde yeni bir örneğin önemli olduğu ViewModel, depolar ve durumlu nesneler için uygulanır.
Koin'i bir Android projesine entegre etmek minimaldir: sadece build.gradle'a bir bağımlılık ekleyin ve Application.onCreate'da startKoin'i çağırın. Koin, Jetpack Compose, Navigation ve WorkManager ile entegrasyon için modüller sağlayarak Hilt'e tam bir alternatif haline gelir.
Özel koin-android-compose kütüphanesi, koinViewModel() ve koinInject() aracılığıyla doğrudan Composable işlevlerine bağımlılıkları enjekte etmeye olanak tanır. Bu, konteyneri her ekranın parametreleri aracılığıyla geçirme ihtiyacını ortadan kaldırır ve otomatik yaşam döngüsü bağlamasıyla ViewModel kodunu daha temiz hale getirir.
Google I/O 2024'e göre Jetpack Compose, yeni Android projeleri için birincil framework haline geldi. Koin, ek yapılandırma olmadan Compose için yerel destek sağlar ve coroutine bağlamını dikkate alarak koinViewModel() aracılığıyla kapsamları otomatik olarak ViewModel yaşam döngüsüne bağlar.
Test için Koin, test modülleriyle izole bir test konteyneri oluşturan ve test tamamlandıktan sonra otomatik olarak kapatan koinTest ve koinTestRule işlevlerini sağlar. Bu, test izolasyonunu garanti eder ve test durumları arasında durum sızıntılarını önler.
Koin'in Jetpack Navigation ile entegrasyonu, koin-androidx-navigation modülü aracılığıyla uygulanır. Her ekranın ViewModel'i, ekran döndürmede durumu korumak ve uygulama askıya alındıktan sonra kurtarmak için SavedStateHandle geçişiyle by viewModel() aracılığıyla otomatik olarak bağımlılıkları alır.
Koin ile ViewModel birim testi için, koin-test-junit5 veya koin-test-junit4 kütüphanesinden koinTestRule kullanılır. Kural, her testten önce test modülleriyle izole bir konteyner oluşturur ve tamamlandıktan sonra otomatik olarak kapatarak test durumları arasında durum sızıntılarını önler. Gerçek bağımlılıklar, MockK aracılığıyla mock'larla değiştirilir: single
Koin 3.x'in temel özelliklerinden biri, Kotlin'de sunucu uygulamaları oluşturmak için Ktor ve masaüstü uygulamalar için Compose Multiplatform desteğidir. Bu, Koin'i enjeksiyon paradigmasını değiştirmeden üç Kotlin platformunu da kapsayan tek DI framework'ü yapar. koin-ktor modülü, Application bloğunda install(Koin) aracılığıyla bağımlılıkları kaydetmeye ve Android'de olduğu gibi by inject() aracılığıyla yollara hizmet enjekte etmeye olanak tanır. Bu, Koin'i mobil istemciden sunucu arka ucuna kadar her mimarideki Kotlin projeleri için evrensel bir DI çözümü yapar.
koin-androidx-navigation modülü aracılığıyla Jetpack Navigation ile Koin entegrasyonu, her ekran için manuel olarak ViewModelProvider.Factory oluşturma ihtiyacını ortadan kaldırır. Çok modüllü projeler için Koin, loadKoinModules aracılığıyla tembel modül yüklemeyi destekler ve her özellik modülünün DI yapılandırmasını bağımsız olarak bağlamasına olanak tanır.
Sıkça Sorulan Sorular
Koin, kod üretimi veya ek açıklama olmadan çalışma zamanında çalışır, bu derlemeleri hızlandırır ancak bağımlılık grafiğini derleme zamanında kontrol etmez. Hilt, derleme zamanında kod üretir ve DI hatalarını daha erken yakalar, ancak karmaşık kurulum gerektirir ve derlemeyi yavaşlatır.
Evet, Koin Kotlin Multiplatform'u tamamen destekler. koin-core kütüphanesi tüm Kotlin platformlarında çalışırken, koin-android ve koin-compose sırasıyla Android ve iOS için platforma özel yetenekler ekler.
Döngüsel bağımlılıklar, çalışma zamanında StackOverflowError'a yol açar. Koin bunları otomatik olarak algılamaz. Çözüm, mimari yeniden düzenlemedir: ortak bir arayüz çıkarma, Listener/Observer desenini kullanma veya ertelenmiş başlatma ile bir fabrika aracılığıyla döngüyü kırma.
Android'de, kapsamlar AndroidScope aracılığıyla Activity veya Fragment yaşam döngüsüne bağlanabilir. Bileşen yok edildiğinde, Koin otomatik olarak ilgili kapsamı kapatır. Özel kapsamlarda (kullanıcı oturumu), kapatma scope.close çağrılarak manuel olarak yapılır.
koin-test modülünden koinTest işlevini kullanın. Test modülleriyle izole bir konteyner oluşturur ve testten sonra otomatik olarak kapanır. Gerçek bağımlılıklar, Mockito veya MockK ile bir modül aracılığıyla mock'larla değiştirilir.
Özet
Anahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.
Ayrıca okuyun