ProgrammatieKotlin Software Engineer

Hoe werken coroutines in Kotlin? Beschrijf het mechanisme van starten, dispatching, annulering en foutafhandeling. Geef een voorbeeld van gebruik en verduidelijk de nuances met betrekking tot contextoverdracht en uitzonderingen.

Slaag voor sollicitatiegesprekken met de Hintsage AI-assistent

Antwoord

Coroutines in Kotlin zijn lichte threads met ondersteuning voor pauzeren en hervatten van berekeningen zonder de OS-threads te blokkeren. Ze worden gestart via functies zoals launch en async binnen een ouder CoroutineScope.

Dispathcing gebeurt via CoroutineDispatcher-objecten die bepalen in welke thread/executor de coroutine wordt uitgevoerd (Dispatchers.Main, Dispatchers.IO, Dispatchers.Default).

Voorbeeld:

fun main() = runBlocking { launch(Dispatchers.IO) { val data = getDataFromNetwork() withContext(Dispatchers.Main) { updateUI(data) } } }

Annulering: Coroutines worden geannuleerd door het annuleren van hun job/Scope, wat een interne uitzondering CancellationException gooit. Coroutines moeten periodiek de annuleringsvlag controleren of pauzefuncties aanroepen om correct te beëindigen.

Foutafhandeling: Uitzonderingen in coroutines kunnen "verdrinken" — bijvoorbeeld, als je de fout in een kindcoroutine niet afhandelt, stopt deze alleen met werken en weet de ouder niet van het probleem. Hiervoor zijn er mechanismen zoals SupervisorJob en CoroutineExceptionHandler.

Nuances van contextoverdracht:

  • Context (bijvoorbeeld Job, Dispatcher, gebruikersitems) wordt geërfd bij het aanmaken van nieuwe coroutines.
  • Je kunt niet zomaar parameters tussen scope's overdragen als ze gesloten of geannuleerd zijn.

Vraag met een valstrik

Wat gebeurt er als binnen een oudercoroutine een van de kindcoroutines met een fout eindigt, terwijl andere doorgaan met werken? Worden alle kinderen geannuleerd?

Velen denken ten onrechte dat de fout "in de kindcoroutine blijft".

Juiste antwoord: Als er een gewone Job (of launch) wordt gebruikt, worden alle kindcoroutines automatisch geannuleerd bij een fout in een van de kinderen. Om te voorkomen dat kindcoroutines worden geannuleerd, gebruik je SupervisorJob of supervisorScope:

supervisorScope { launch { error("fail") } launch { println("Deze code zal werken") } }

Voorbeelden van werkelijke fouten door onwetendheid over de nuances van het onderwerp


Verhaal

Onjuiste foutafhandeling — flow-crash: In het project werden coroutines gebruikt om gegevens te laden. Uitzonderingen "verdrongen" zich binnen kindcoroutines, waardoor het niveau van retry/recovery niet werkte, en het hoofdscherm leeg bleef zonder foutmeldingen voor de gebruiker.


Verhaal

Bevroren UI door werken met Dispatchers.Main: Een jonge Android-ontwikkelaar startte een zware rekenopdracht op Dispatchers.Main — de UI begon te "bevriezen". Er was geen begrip dat zware rekeningen op Dispatchers.Default of Dispatchers.IO moesten worden uitgevoerd.


Verhaal

AbortError bij het annuleren van de ouderlijke scope: Een van de ontwikkelaars hield er geen rekening mee dat bij het annuleren van de ouderlijke scope alle kindcoroutines beëindigd worden met annulering, en een kritieke operatie (gegevens opslaan) niet was voltooid.