Sobes.tech
Middle

Kuidas saab Flow'ss voogusid vahetada? Millises voos töötab Flow?

sobes.tech AI

Vastus AI-lt

Vaikimisi Flow töötab selle vooga, millest see käivitati. Voodite vahetamiseks saab kasutada flowOn operaatorit.

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

// Näidissüsteem, mis tagastab Flow
fun simpleFlow(): Flow<Int> = flow {
    logThread("Flow algas") // Logimine voog, kus käivitatakse flow builder
    for (i in 1..3) {
        emit(i) // Väärtuste saatmine
    }
}

fun main() = runBlocking {
    simpleFlow()
        .flowOn(Dispatchers.IO) // Ülemise (emitters) voogedastuse vahetamine Dispatchers.IO-ks
        .collect { value ->
            logThread("Kogutud $value") // Logimine voog, kus väärtused kogutakse
        }
}

// Abi funktsioon voogude logimiseks
fun logThread(msg: String) {
    println("[$msg] [${Thread.currentThread().name}]")
}

flowOn operaator mõjutab voogu, kus operatsioonid enne seda (sh flow builder). Pärast flowOn toimuvad operatsioonid sellel niidil, mis on näidatud flowOn argumentides. Kui on mitu flowOn, siis igaüks neist mõjutab oma osa enne seda.

Näide mitme flowOn-ga:

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

fun simpleFlowWithMultipleFlowOn(): Flow<String> = flow {
    logThread("Flow builder algas") // Töötab esimese määratud `flowOn`-ga
    emit("A")
    emit("B")
}.map {
    logThread("Kaardistamine $it") // Töötab teise määratud `flowOn`-ga
    it.toLowerCase()
}.flowOn(Dispatchers.Default) // Teine `flowOn` mõjutab `map` ja `flow` builderit
.filter {
    logThread("Filtreerimine $it") // Töötab `collect`-i välise voogena (tavaliselt main/runBlocking)
    true
}.flowOn(Dispatchers.IO) // Esimene `flowOn` mõjutab `map` ja `flow` builderit

fun main() = runBlocking {
    simpleFlowWithMultipleFlowOn().collect { value ->
        logThread("Kogumine $value") // Töötab `runBlocking`-i vooges (main)
    }
}

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

Selles näites:

  • flow builder ja map töötavad Dispatchers.Default-is (sest see on viimane flowOn nende ees).
  • filter töötab vooges, millelt collect kutsutakse, see tähendab runBlocking-i vooges (tavaliselt Main Androidis).

Oluline on mõista, et flowOn loob vahekiibi ja ei ole "läbipaistev" vahetus.