Corrutines¶
Les corrutines són una de les característiques més potents i diferencials del llenguatge Kotlin. Serveixen per gestionar tasques asíncrones i concurrents d’una manera molt més senzilla, segura i llegible que amb fils (threads) tradicionals.
- https://www.youtube.com/watch?v=vQ0w4zAe68A&t=943
- https://developer.android.com/kotlin/coroutines?hl=es-419
Què és una corrutina?¶
Una corrutina és una unitat d'execució lleugera que es pot pausar i reprendre sense bloquejar el fil principal del programa.
- Es podrien descriure com “threads lleugers”
- Permeten fer processos costosos sense congelar la UI
- Fan el codi asíncron més intuïtiu i lineal
- Es poden cancelar automàticament
Per què s’utilitzen?¶
Quan programem, especialment en aplicacions Android, sovint tenim tasques com:
- Accedir a la base de dades
- Fer peticions HTTP (APIs)
- Llegir fitxers
- Fer càlculs costosos
Si aquestes tasques s'executessin al fil principal, bloquejaria la interfície gràfica.
Les corrutines resolen aquest problema executant-se en un fil secundari i tornant el resultat quan està llest.
Elements principals de les corrutines¶
1. CoroutineScope¶
És el “context” on viuen les corrutines.
Exemples de scopes:
| Scope | Ús |
|---|---|
| GlobalScope | corrutina global durant tota l'app |
| MainScope | vinculat a UI |
| lifecycleScope | Android – vinculat al cicle de vida |
| viewModelScope | Android – s’atura quan el ViewModel mor |
2. launch vs async¶
launch¶
Executa una corrutina sense retornar resultat
lifecycleScope.launch {
println("Això és una tasca asíncrona")
}
async¶
Retorna un objecte Deferred
val resultat = async {
10 + 20
}.await()
println(resultat)
3. Suspend functions¶
Una funció marcada amb suspend pot ser pausada i continua en un altre moment.
suspend fun carregarDades(): String {
delay(2000) // simula temps d’espera
return "Dades carregades"
}
Només es pot cridar des de:
- una corrutina
- una altra funció suspend
Dispatchers (On s’executen?)¶
Els dispatchers indiquen en quin fil s'executa la corrutina:
| Dispatcher | Ús |
|---|---|
| Dispatchers.Main | tasques de UI |
| Dispatchers.IO | fitxers, base de dades, xarxa |
| Dispatchers.Default | càlculs pesats |
| Dispatchers.Unconfined | poc utilitzat |
Exemple:
launch(Dispatchers.IO) {
val dades = carregarDades()
withContext(Dispatchers.Main) {
// actualitzar UI
textView.text = dades
}
}
Què és withContext?¶
withContext és una funció de suspensió (suspend) que permet canviar el dispatcher o context dins d’una corrutina i executar un bloc de codi en aquest nou context, sense crear una nova corrutina.
És útil per fer tasques de fons (IO, càlculs) i després tornar a la UI per actualitzar-la.
Retorna el resultat del bloc que executa.
val resultat = withContext(Dispatchers.IO) {
// codi que s'executa en un fil d'entrada/sortida (IO)
carregarDadesPesades()
}
Diferència entre withContext launch i async¶
| Funció | Quan usar-la | Retorna resultat? |
|---|---|---|
| launch | Crear una corrutina nova | No |
| async | Crear corrutina que retorna un resultat | Sí, Deferred.await() |
| withContext | Canviar context dins d’una corrutina existent | Sí, retorna el valor del bloc |