Sobes.tech
Middle+

Cum să sincronizați corutinele în Android?

sobes.tech AI

Răspuns de la AI

Pentru sincronizarea corutinelor în Android, se pot folosi mai multe abordări, în funcție de sarcina specifică:

  • Join: Așteptarea finalizării altei corutine.

    // Pornim prima corutină
    val job1 = CoroutineScope(Dispatchers.Default).launch {
        delay(1000)
        println("Job 1 terminat")
    }
    
    // Pornim a doua corutină
    val job2 = CoroutineScope(Dispatchers.Default).launch {
        delay(500)
        println("Job 2 terminat")
    }
    
    // Așteptăm finalizarea ambelor corutine
    job1.join()
    job2.join()
    
    println("Toate joburile au fost finalizate")
    
  • Await: Așteptarea rezultatului unei operații asincrone reprezentate de Deferred.

    // Operație asincronă care returnează un rezultat
    val deferredResult = CoroutineScope(Dispatchers.Default).async {
        delay(1000)
        "Rezultatul din async"
    }
    
    // Așteptăm rezultatul
    val result = deferredResult.await()
    println(result)
    
  • CoroutineScope.coroutineScope: Crearea unui nou domeniu de vizibilitate care se va termina doar după finalizarea tuturor corutinelor copil. Util pentru concurența structurată.

    suspend fun doParallelWork() {
        coroutineScope { // Creăm un nou scope de concurență structurată
            launch { delay(1000); println("Task 1 terminat") }
            launch { delay(500); println("Task 2 terminat") }
        } // Acest punct va fi atins doar după finalizarea task-urilor 1 și 2
        println("Toate task-urile paralele au fost finalizate")
    }
    
  • Semantica actorilor (Channel): Pentru schimbul de mesaje și sincronizarea accesului la date modificabile între corutine.

    // Creăm un canal pentru schimbul de Int
    val channel = Channel<Int>()
    
    CoroutineScope(Dispatchers.Default).launch {
        // Trimitem date în canal
        for (i in 1..5) {
            channel.send(i)
        }
        channel.close() // Închidem canalul după trimitere
    }
    
    CoroutineScope(Dispatchers.Default).launch {
        // Primim date din canal
        for (value in channel) {
            println("Primite $value")
        }
    }
    
  • Mutex: Pentru a asigura accesul exclusiv la o resursă comună.

    import kotlinx.coroutines.sync.Mutex
    import kotlinx.coroutines.sync.withLock
    
    val mutex = Mutex()
    var counter = 0
    
    suspend fun incrementCounter() {
        mutex.withLock { // Obține mutex-ul
            counter++
            // Mutex-ul va fi eliberat automat la ieșirea din bloc
        }
    }
    

Alegerea metodei depinde de ceea ce trebuie sincronizat exact: așteptarea finalizării, obținerea rezultatului, gestionarea sarcinilor paralele, schimbul de date sau accesul exclusiv. coroutineScope este abordarea recomandată implicit pentru concurența structurată.