Undervejs i udviklingen af min app har jeg brugt nogle forskellige eksterne pakker til at tage vare på forskellige opgaver.

Her vil jeg kort beskrive Koin, som er er et framework der håndterer dependency injection i Kotlin. Dependency injection er naturligvis smart fordi det medvirker til at man kan lave kode som ikke er så hårdt koblet sammen på kryds og tværs.

Koin opsætning / gradle

I din build.gradle (module:app) skal linjen “implementation ‘org.koin:koin-androidx-scope:2.0.0-rc-2’” indsættes under dependencies:

dependencies {
  ...
  implementation 'org.koin:koin-androidx-scope:2.0.0-rc-2'
  ...
}

Husk at sync’e efter du har lavet ændringer i en eller flere gradle-filer.

Koin opsætning / module

Opret herefter en kotlin-fil: “AppModule.kt”. Navnet er ikke vigtigt og den skal ikke indeholde nogen klasse. Jeg oprettede en pakke der hedder services som den ligger i, men det er i et forsøg på at strukturere koden så den giver mening for mig, filen må gerne ligge i rod-mappen for al din anden kode.

Filen skal bruges til at registrere dependencies i:

val appModule = module{
    single {RequestRepository(get())}
}

Man kan give sine dependencies forskellige lifetime scopes, og i ovenstående bruges single, som betyder at det er den samme instans af RequestRepository som sendes rundt når der bedes om den.

Man kan desuden bruge scope (som kobler instansen op på den lifetime som dit nuværende scope har) og factory (som altid skaber en ny instans og som ikke kan sendes rund i programmet vha Koin frameworket).

Koin opsætning / startKoin()

I MainActivity.kt skal man starte Koin i OnCreate() metoden med startKoin:

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        startKoin {
            // Android context
            androidContext(this@MainActivity)
            // modules
            modules(appModule)
        }
      // mere kode...?
    }

Nu har du foretaget den opsætning der skal til for at kunne bruge frameworket.

Koin / tilgå dependencies

Men for at kunne få fat i en dependency fra Koin kan du gøre følgende:

  private val requestRepo: RequestRepository by inject()

og nu er RequestRepositorys instans tilgængelig for klassen

Reflektion om DI og Koin

I skrivende stund er det muligvis overkill at bruge et framework til dependency injection i lige netop dette projekt. Jeg bruger det kun til at sende instansen af mit repo rundt. Jeg kunne have lavet repoet som en singleton (og det er principielt det som Koin gør nu) og bare kaldt efter instansen når jeg har brug for den.

Men jeg følte alligevel at det både er en god ide og en god øvelse lige at have sådan en struktur med i projektet. Dog bør det nævnes at et framework der håndterer dependency injection er ikke en garanti for at man undgår at lave sammenkoblet spaghetti kode. Men det er et værktøj der kan afhjælpe det, hvis man samtidig prøver at planlægge og strukturere sin kode.

Yderligere ressourcer

Denne opsætning afspejler hvad jeg har gjort i mit projekt. Der findes andre Koin-pakker man kan hente og andre måder at lave opsætningen på, så for mere info linker jeg til Koins dokumentation, som virkelig er et kig værd.

Jeg linker til Koins reference dokumentation, da de mere “light weight” vejledninger på insert-koin.io i nogle tilfælde er forkerte, men i reference dokumentationen fandt jeg retvisende eksempler og lignende som var nemt at bruge.