Sobes.tech
Middle

Kā var pārslēgt plūsmas Flow? Kurā plūsmas daļā darbojas Flow?

sobes.tech AI

Atbilde no AI

Pēc noklusējuma Flow darbojas tajā pavedienā, no kura tas tika palaists. Pavedienu pārslēgšanu var veikt ar operatoru flowOn.

import kotlinx.coroutines.CoroutineDispatcher // Par CoroutineDispatcher
import kotlinx.coroutines.Dispatchers // Par Dispatchers
import kotlinx.coroutines.flow.Flow // Par Flow
import kotlinx.coroutines.flow.flow // Par flow
import kotlinx.coroutines.flow.flowOn // Par flowOn
import kotlinx.coroutines.runBlocking // Par runBlocking

// Piemēra funkcija, kas atgriež Flow
fun simpleFlow(): Flow<Int> = flow {
    logThread("Flow sāka darboties") // Žurnāla izvadīšana pavedienā, kur sākas flow būvētājs
    for (i in 1..3) {
        emit(i) // Vērtību emitēšana
    }
}

fun main() = runBlocking {
    simpleFlow()
        .flowOn(Dispatchers.IO) // Pārsūtām augšējo (emitētājus) uz Dispatchers.IO
        .collect { value ->
            logThread("Savākti $value") // Žurnāla izvadīšana pavedienā, kur tiek savāktas vērtības
        }
}

// Palīdzības funkcija žurnāla izvadīšanai
fun logThread(msg: String) {
    println("[$msg] [${Thread.currentThread().name}]")
}

Operator flowOn ietekmē pavedienu, kurā tiek izpildīti operatori pirms tā (ieskaitot flow būvētāju). Operatori pēc flowOn tiek izpildīti uz pavediena, kas norādīts flowOn argumentā. Ja ir vairāki flowOn, katrs ietekmē savu daļu pirms tā.

Piemērs ar vairākiem flowOn:

import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.runBlocking

fun simpleFlowWithMultipleFlowOn(): Flow<String> = flow {
    logThread("Flow būvētājs sāka darboties") // Darbojas uz pirmā norādītā `flowOn`
    emit("A")
    emit("B")
}.map {
    logThread("Kartēšana $it") // Darbojas uz otra norādītā `flowOn`
    it.toLowerCase()
}.flowOn(Dispatchers.Default) // Otra `flowOn` ietekmē uz `map` un `flow` būvētāju
.filter {
    logThread("Filtrēšana $it") // Darbojas uz pavediena, no kura izsauc `collect` (parasti maina/runBlocking)
    true
}.flowOn(Dispatchers.IO) // Pirmais `flowOn` ietekmē uz `map` un `flow` būvētāju

fun main() = runBlocking {
    simpleFlowWithMultipleFlowOn().collect { value ->
        logThread("Vāko $value") // Darbojas uz `runBlocking` pavediena (main)
    }
}

fun logThread(msg: String) {
    println("[$msg] [${Thread.currentThread().name}]")
}

Šajā piemērā:

  • flow būvētājs un map darbosies uz Dispatchers.Default (jo tas ir pēdējais flowOn ķēdē pirms tiem).
  • filter darbosies uz pavediena, no kura tiek izsaukts collect, tas ir, uz runBlocking pavediena (parasti galvenais Android).)

Svarīgi saprast, ka flowOn rada starpposma buferi un nav "caurspīdīgs" pārslēgums.