Cum să configurezi și să utilizezi corutinele în proiecte Kotlin?
sobes.tech AI
Răspuns de la AI
Pentru configurarea corutinelor, trebuie să adăugați dependența corespunzătoare în fișierul build.gradle.
// build.gradle (modulul aplicației)
dependencies {
//... alte dependențe
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3") // Pentru JVM, Android, JS, Native
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3") // Pentru Android (dacă aveți nevoie de Dispatchers.Main)
}
Utilizarea corutinelor include:
-
Domeniu de viață (Scope): Stabilirea domeniului în care vor fi executate corutinele și gestionarea ciclului lor de viață.
GlobalScope: Domeniul întregii aplicații, folosiți cu precauție, deoarece poate duce la scurgeri de memorie.CoroutineScope: Creat explicit, permite controlul anulării corutinelor.- Domenii predefinite în cadre (de exemplu,
lifecycleScopeîn Android ViewModel).
// Exemplu cu CoroutineScope val myScope = CoroutineScope(Dispatchers.Default + SupervisorJob()) // Crearea unui domeniu cu Dispatcher și Job fun performBackgroundTask() { myScope.launch { // Pornirea unei corutine // Proces de calcul lung } } fun cancelAllTasks() { myScope.cancel() // Anulare toate corutinele din domeniu } -
Constructori de corutine (Builders): Funcții pentru a porni corutine.
launch: Pornește o corutină care nu returnează un rezultat explicit (Job).async: Pornește o corutină care returnează un rezultat sub formaDeferred.
import kotlinx.coroutines.* suspend fun fetchData() = coroutineScope { // coroutineScope - builder pentru concurență structurată val data1 = async { networkCall1() } // async returnează Deferred val data2 = async { networkCall2() } // ... procesare date după primire data1.await() // Obține rezultatul din Deferred, pune corutina în așteptare până se finalizează data2.await() } suspend fun networkCall1(): String { delay(1000) // Simulare cerere de rețea return "Data 1" } suspend fun networkCall2(): String { delay(1500) return "Data 2" } fun startFetching() = runBlocking { // runBlocking - builder pentru blocarea thread-ului curent launch { // launch returnează Job println("Fetching data...") fetchData() println("Data fetched!") } } -
Dispatchers: Determină pe ce thread sau pool de thread-uri va fi executată corutina.
Dispatchers.Default: Pentru sarcini intensive CPU.Dispatchers.IO: Pentru operații I/O blocante (fișiere, rețea).Dispatchers.Main: Thread principal (doar pentru Android și Swing/JavaFX).Dispatchers.Unconfined: Pornește corutina în thread-ul apelant, se pune în așteptare și apoi se reia în thread-ul care a reluat execuția.
import kotlinx.coroutines.* fun simpleTask() { GlobalScope.launch(Dispatchers.IO) { // Specificarea dispatcher-ului // Executarea operației I/O println("Running on thread: ${Thread.currentThread().name}") } } fun main() = runBlocking { launch(Dispatchers.Default) { println("Default thread: ${Thread.currentThread().name}") } launch(Dispatchers.Unconfined) { println("Unconfined thread 1: ${Thread.currentThread().name}") delay(100) // Punere în așteptare println("Unconfined thread 2: ${Thread.currentThread().name}") // Reîncepere în alt thread (posibil) } delay(200) // Așteptarea finalizării corutinelor } -
Funcții de suspendare (Suspending functions): Funcții marcate cu
suspend, care pot fi puse în pauză și reluate fără a bloca thread-ul. Pot fi apelate doar din alte funcții suspend sau dintr-un bloc de corutine. -
Gestionarea anulării și excepțiilor: Corutinele suportă anulare structurată și propagarea excepțiilor.
- Anulare:
import kotlinx.coroutines.* fun cancellableTask() = GlobalScope.launch { try { repeat(1000) { i -> println("Working $i ...") delay(100) // funcție suspend care respectă anularea } } catch (e: CancellationException) { println("Task was cancelled!") } finally { println("Cleaning up...") } } fun main() = runBlocking { val job = cancellableTask() delay(500) // Așteptare job.cancelAndJoin() // Anulare și așteptare finalizare } - Excepții: În cazul
launch, excepția necapturată va duce la prăbușirea aplicației (implicit în Android). În cazulasync, excepția va fi aruncată la apelulawait(). Pentru control mai fin, se folosescCoroutineExceptionHandlersauSupervisorJob.
import kotlinx.coroutines.* fun main() = runBlocking { val handler = CoroutineExceptionHandler { _, exception -> println("Caught exception: $exception") } val job = GlobalScope.launch(handler) { // Aplicarea handler-ului throw IllegalStateException("Something went wrong") } job.join() // Așteptarea finalizării } - Anulare: