Koin — bu nədir, Dependency Injection prinsipləri və necə işləyir

Müəllif: IT Sectr Dərc olunub: 2026-05-04 Oxuma vaxtı: 8 dəq

Koin — kod yaradılması, refleksiya və annotasiyalar olmadan işləyən Kotlin üçün DI freymvorkudur. Kitabxana modulları təsvir etmək üçün DSL-dən istifadə edir və asılılıqları Android, Ktor və Multiplatform dəstəyi ilə yüngül konteyner vasitəsilə yerləşdirir. Koin-in rəsmi sənədlərinə görə, freymvork modullar, skoplər və minimal boilerplate ilə Jetpack Compose üçün daxili dəstək təmin edir.

Başlıca məqamlar

  • Koin — refleksiya və kod yaradılması olmadan DSL istifadə edən Kotlin üçün DI freymvorkudur.
  • Modul — single və factory funksiyaları vasitəsilə asılılıq qeydiyyatlarının məntiqi qruplaşdırılması.
  • single — nüsxəsi bir dəfə yaradılan sinqltonun qeydiyyatı.
  • factory — hər sorğuda yeni nüsxə yaradan qeydiyyat.
  • Scope — asılılığın ömür dövrünün komponentə, məsələn Activity-yə bağlılıq mexanizmi.

Koin nədir və nə ilə fərqlənir

Koin — təmiz dildə, refleksiya, annotasiya və ya kod yaradılması olmadan yazılmış Kotlin üçün DI freymvorkudur. Kompilyasiya mərhələsində annotasiya prosessoru və kod yaradılması tələb edən Dagger Hilt-dən fərqli olaraq, Koin yalnız runtime-da, modulları təsvir etmək üçün yüngül DSL istifadə edərək işləyir.

Koin-in əsas ideyası — mürəkkəb asılılıq qrafşları və komponent ağacları konsepsiyalarını öyrənmək məcburiyyəti olmadan asılılıqların qeydiyyatı və həlli üçün sadə API təmin etməkdir. Tərtibatçı konteyner üçün hansı siniflərin mövcud olduğunu təsvir edir, Koin isə onları konstruktor və ya by inject gecikmiş delegatları vasitəsilə avtomatik yerləşdirir. Freymvork Kotlin Multiplatform ilə tam uyğumdur ki, bu da Android, iOS və server tərəfində vahid DI yanaşmasından istifadə etməyə imkan verir.

Kotlin Developers Community sorğusuna (2025) görə, Koin kommersiya Android layihələrinin 31%-də istifadə olunur, populyarlıq baxımından yalnız Hilt-dən (47%) geri qalır. Seçimin əsas səbəbi — konfiqurasiyanın sadəliyi və kod yaratmağa ehtiyac olmaması, bu da layihənin qurulmasını sürətləndirir.

Tərtibatın sürətli başlamasının vacib olduğu orta və böyük layihələr üçün və ya Hilt-in memarlıq səbəblərdən mövcud olmadığı Kotlin Multiplatform həlləri üçün Koin-i seçin.

Koin refleksiya və kod yaradılmasından istifadə etmir — bütün qeydiyyatlar reified tipli inline funksiyalara əsaslanır ki, onlar kompilyasiya mərhələsində funksiya bədəninə konkret tipi yerləşdirirlər. Bu, Koin-i son APK ölçüsünə görə ən yüngül DI freymvorklarından birinə çevirir: Koin-in əlavə edilməsi tətbiqin ölçüsünü cəmi 100–150 KB artırır, halbuki Dagger Hilt yaradılan kod hesabına təxminən 500 KB əlavə edir.

Koin konteyneri və DSL necə işləyir

Koin konteyneri konfiqurasiya ilə lambda qəbul edən startKoin funksiyası vasitəsilə işə salınır. Bu lambdanın içərisində qeydiyyatlarla modullar təsvir olunur — DI məntiqinin əsas tikinti bloku.

startKoin və modullar

startKoin funksiyası GlobalContext vasitısilə tətbiqin istənilən nöqtəsindən əlçatan qlobal konteyner yaradır, lakin çoxmodullu layihələrdə izolyasiya olunmuş konteynerlər yaratmaq üçün KoinApplication istifadə etmək tövsiyə olunur. Android-dé işə salma üçün avtomatik olaraq Application həyat dövrünə bağlanan AndroidContext istifadə olunur. Modullar Module nüsxələrinin siyahısını qəbul edən modules parametri vasitəsilə qeydiyyatdan keçirilir.

kotlin
val networkModule = module {
    single {
        OkHttpClient()
    }
    single {
        Retrofit.Builder()
            .baseUrl("https://api.example.com")
            .build()
    }
}

startKoin {
    modules(networkModule)
}

Hər modul single (sinqlton) və ya factory (yeni nüsxə) vasitəsilə təriflər ehtiva edir. Təriflər get() vasitəsilə digər qeydiyyatdan keçmiş asılılıqlara istinad edə bilər ki, bu da tipləri açıq göstərmədən və boilerplate kodu olmadan yerləşdirmə qrafşı yaradır.

DSL və inline funksiyalar

Koin kontekstdən tip çıxarmaq üçün reified parametrləri olan inline funksiyalardan fəal istifadə edir. Bu, sinfi açıq göstərmədən qeydiyyat yazmağa imkan verir: single { MyService() } avtomatik olaraq lambdanın qaytardığı dəyərə görə tipi müəyyən edir.

Dagger-dən fərqli olaraq, Koin asılılıq qrafşını kompilyasiya mərhələsində yoxlamır — bütün səhvlər həll olunmamış asılılığa ilk müraciətdə runtime-da aşkarlanır. Bu, kodu əhəmiyyətlı dərəcədə sadələşdirən və qurulmanı sürətləndirən, lakin DI konfiqurasiyasının test əhatəsini tələb edən bir kompromisdir. Bir çox komanda kompilyasiya zamanı yoxlamalarının olmamasına baxmayaraq, Koin-i məhz inkişaf sürəti və sadəliyi üçün seçir.

Koin 3.5 versiyasında Koin Annotations plaqini vasitəsilə kompilyasiya mərhələsində qrafın eksperimental yoxlaması peyda oldu. Tərtibatçı @Module və @KoinComponent annotasiyalarını əlavə edir, plaqin isə qurulma zamanı işləyən doğrulama kodu yaradır. Lakin Koin-in əsas üstünlüyü — kod yaradılmasının olmaması — bu rejimdə itir, ona görə də əksər komandalar testlər vasitəsilə runtime yoxlamaları ilə klassik DSL yanaşmasından istifadə etməyə davam edir.

Koin-də asılılıqların yerləşdirilməsi üsulları

Koin asılılıqların yerləşdirilməsi üçün bir neçe üsul təqdim edir: by inject(), get() və konstruktor vasitəsilə birbaşa ötürülmə. Ösulun seçimi istifadə kontekstindən asılıdır.

by inject() — gecikmiş yerləşdirmə

by inject delegatı — ViewModel və Android fraqmentlərində ən geniş yayılmış yerləşdirmə üsuludur. Asılılıq gecikmiş şəkildə — yalnız xassəyə ilk müraciətdə işə salınır. Bu, dərhal lazım olmaya biləcək resurs tutumlu servislər üçün səmərəlidir.

kotlin
class MainViewModel : ViewModel() {
    private val repository: UserRepository by inject()

    fun loadUsers() {
        repository.fetchAll()
    }
}

get() — açıq əldə etmə

get funksiyası asılılığın nüsxəsini dərhal qaytarır. Qeydiyyat zamanı fabrik lambdalarının içərisində və ya asılılığın gecikmiş işə salma olmadan sinxron kontekstdə lazım olduğu hallarda istifadə olunur. by inject()-ən fərqli olaraq, get() gecikmiş yükləməni dəstəkləmir və çağrış anında konteynerin artıq işə salınmasını tələb edir.

Koin-də modullar və skoplər

Scope Koin-də — asılılıqların ömür dövrünü Activity, Fragment və ya istifadəçi sessiyası kimi müəyyən bir komponentə bağlamaq mexanizmidir. Bu, Android tətbiqlərində yaddaşı idarə etmək üçün əsas funksionallıqdır.

scope — komponentə bağlılıq

Modul daxilində scope funksiyası bağlı komponent yaşadığı müddət yaşayan skop yaradır. Skopda qeydiyyatdan keçmiş bütün asılılıqlar bağlandıqda məhv olur ki, bu da yaddaş sızıntılarının qarşısını alır.

kotlin
val userScope = module {
    scope<UserSession> {
        scoped {
            UserRepository(get())
        }
        scoped {
            SessionManager(get())
        }
    }
}

scoped funksiyası yalnız skop daxilində mövcud olacaq asılılığı qeydiyyatdan keçirir. Skop bağlandıqda bütün scoped obyektlər zibil yığıcı üçün əlçatmaz olur.

single vs factory

single — gecikmiş işə salma ilə bütün tətbiq üçün vahid nüsxənin qeydiyyatı. Vəzifəsiz servislər üçün istifadə olunur: şəbəkə müştəriləri, keşlər, loggerlər.

factory — hər get() çağrışı yeni nüsxə yaradır. Hər müraciətdə təzə nüsxənin vacib olduğu ViewModel, repozitoriyalar və vəziyyətli obyektlər üçün tətbiq olunur.

Android layihələrində Koin

Koin-in Android layihəsinə inteqrasiyı minimaldır: build.gradle-ə asılılıq əlavə etmək və Application.onCreate-də startKoin çağırmaq kifayətdir. Koin Jetpack Compose, Navigation və WorkManager ilə inteqrasiya üçün modullar təmin edir ki, bu da onu Hilt-ə tam hüquqlu alternativ edir.

Xüsusi koin-android-compose kitabxanası koinViewModel() və koinInject() funksiyaları vasitəsilə birbaşa Composable funksiyalarında asılılıqları yerləşdirməyə imkan verir. Bu, konteyneri hər ekranın parametrləri vasitəsilə ötürmək ehtiyacını aradan qaldırır və həyat dövrü ilə avtomatik əlaqə sayəsində ViewModel kodunu daha təmiz edir.

Google I/O 2024-ə görə, Jetpack Compose yeni Android layihələri üçün əsas freymvorka çevrildi. Koin əlavə konfiqurasiya olmadan Compose-ın doğma dəstəyini təmin edir, koinViewModel() vasitəsilə skoplərı ViewModel həyat dövrü ilə avtomatik əlaqələndirir və coroutine kontekstini nəzərə alır.

Test etmək üçün Koin test modulları ilə izolyasiya olunmuş konteyner yaradan və test bitdikdən sonra onu avtomatik bağlayan koinTest və koinTestRule funksiyalarını təqdim edir. Bu, testlərin izolyasiyasını təmin edir və test halları arasında vəziyyət sızıntılarının qarşısını alır.

Koin-in Jetpack Navigation ilə inteqrasiyası koin-androidx-navigation modulu vasitəsilə həyata keçirilir. Hər ekranın ViewModel-i avtomatik olaraq by viewModel() vasitəsilə asılılıqları alır və ekranın döndərilməsi zamanı vəziyyəti qorumaq və tətbiq kiçildildikdən sonra bərpa etmək üçün SavedStateHandle ötürülür.

ViewModel-in Koin ilə vahid testi üçün koin-test-junit5 və ya koin-test-junit4 kitabxanasından koinTestRule istifadə olunur. Qayda hər testdən əvvəl test modulları ilə izolyasiya olunmuş konteyner yaradır və bitdikdən sonra onu avtomatik bağlayır, test halları arasında vəziyyət sızıntılarının qarşısını alır. Həqiqi asılılıqlar MockK vasitəsilə mock-larla əvəz olunur: single { mockk() } qeydiyyatları olan modul əsas modulu əvəz edir və testdə ViewModel proqnozlaşdırıla bilən asılılıq davranışı alır.

Koin 3.x-in əsas imkanlarından biri Kotlin-də server tətbiqləri yaratmaq üçün Ktor və desktop tətbiqləri üçün Compose Multiplatform dəstəyidir. Bu, Koin-i yerləşdirmə paradigm dəyişmədən Kotlin-in hər üç platformasını əhatə edən yeganə DI freymvorku edir. koin-ktor modulu Application blokunda install(Koin) vasitəsilə asılılıqları qeydiyyatdan keçirməyə və Android-də olduğu kimi by inject() vasitəsilə servisləri marşrutlara yerləşdirməyə imkan verir. Bu, Koin-i mobil müştəridən server backendinə qədər istənilən memarlıqlı Kotlin layihələri üçün universal DI həllinə çevirir.

Koin-in Jetpack Navigation ilə koin-androidx-navigation modulu vasitəsilə inteqrasiyası hər ekran üçün əl ilə ViewModelProvider.Factory yaratmaq ehtiyacını aradan qaldırır. Çoxmodullu layihələr üçün Koin loadKoinModules vasitƏsilƏ modulların gecikmiş yüklənməsini dəstəkləyir ki, bu da hər bir funksiya modulunun DI konfiqurasiyasını müstəqil qoşmağa imkan verir.

Tez-tez verilən suallar

Koin Dagger Hilt-dən nə ilə fərqlənir?

Koin kod yaradılması və annotasiyalar olmadan runtime-da işləyir, bu da qurulmanı sürətləndirir, lakin asılılıq qrafşını kompilyasiya mərhələsində yoxlamır. Hilt kompilyasiya zamanı kod yaradır və DI səhvlərini daha tez tutur, lakin mürəkkəb konfiqurasiya tələb edir və qurulmanı yavaşlatır.

Koin Kotlin Multiplatform-u dəstəkləyirmi?

Bəli, Koin Kotlin Multiplatform-u tam dəstəkləyir. koin-core kitabxanası bütün Kotlin platformalarında işləyir, koin-android və koin-compose isə müvafiq olaraq Android və iOS üçün platforma-spesifik imkanlar əlavə edir.

Koin-də tsiklik asılılıqları necə idarə etməli?

Tsiklik asılılıqlar runtime-da StackOverflowError-a səbəb olur. Koin onları avtomatik aşkarlamır. Həll yolu — memarlığın refaktorinqi: ümumi interfeysin ayrılması, Listener/Observer nümunəsinin istifadəsi və ya gecikmiş işə salma ilə fabrik vasitəsilə dövrün qırılması.

Skopləri əl ilə bağlamaq lazımdırmı?

Android-də skoplər AndroidScope vasitəsilə Activity və ya Fragment-in həyat dövrünə bağlana bilər. Komponent məhv olduqda Koin müvafiq skopu avtomatik bağlayır. İstifadəçi skoplərində (istifadəçi sessiyası) bağlanma scope.close çağrışı ilə əl ilə həyata keçirilir.

Koin ilə kodu necə test etməli?

koin-test modulundan koinTest funksiyasından istifadə edin. O, test modulları ilə izolyasiya olunmuş konteyner yaradır və testdən sonra avtomatik bağlanır. Həqiqi asılılıqlar Mockito və ya MockK ilə modul vasitəsilə mock-larla əvəz olunur.

Nəticə

  • Koin — refleksiya, annotasiya və kod yaradılması olmadan DSL ilə Kotlin üçün DI freymvorkudur.
  • Modullar qeydiyyatları single (sinqlton) və factory (yeni nüsxə) vasitəsilə qruplaşdırır.
  • startKoin by inject() və get() vasitəsilə əlçatan qlobal konteyneri işə salır.
  • Scope asılılıqların ömür dövrünü Android komponentinin həyat dövrünə bağlayır.
  • Compose-də yerləşdirmə koinViewModel() və koinInject() vasitəsilə həyata keçirilir.
  • Koin Kotlin Multiplatform-u dəstəkləyir, bütün platformalarda vahid DI yanaşmasına imkan verir.
  • DI səhvləri runtime-da aşkarlanır, ona görə də konfiqurasiyanın test əhatəsi məcburidir.

Açar təslim mobil tətbiq hazırlayacağıq

IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.

Layihəni müzakirə et

Həm də oxuyun