Middle
Come si possono cambiare i thread in Flow? Su quale thread funziona Flow?
sobes.tech AI
Risposta dell'AI
Per impostazione predefinita, Flow funziona sul thread da cui è stato avviato. È possibile cambiare thread usando l'operatore flowOn.
import kotlinx.coroutines.CoroutineDispatcher // Per CoroutineDispatcher
import kotlinx.coroutines.Dispatchers // Per Dispatchers
import kotlinx.coroutines.flow.Flow // Per Flow
import kotlinx.coroutines.flow.flow // Per flow
import kotlinx.coroutines.flow.flowOn // Per flowOn
import kotlinx.coroutines.runBlocking // Per runBlocking
// Esempio di funzione che restituisce un Flow
fun simpleFlow(): Flow<Int> = flow {
logThread("Flow avviato") // Log del thread in cui viene avviato il builder di flow
for (i in 1..3) {
emit(i) // Emetti valori
}
}
fun main() = runBlocking {
simpleFlow()
.flowOn(Dispatchers.IO) // Cambia upstream (emettitori) a Dispatchers.IO
.collect { value ->
logThread("Raccolto $value") // Log del thread in cui vengono raccolti i valori
}
}
// Funzione ausiliaria per il logging del thread
fun logThread(msg: String) {
println("[$msg] [${Thread.currentThread().name}]")
}
L'operatore flowOn influisce sul thread in cui vengono eseguiti gli operatori prima di esso nella catena (incluso il flow builder). Gli operatori dopo flowOn vengono eseguiti sul thread specificato nell'argomento flowOn. Se ci sono più flowOn nella catena, ciascuno influisce sulla parte della catena prima di esso.
Esempio con più flowOn:
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.runBlocking
fun simpleFlowWithMultipleFlowOn(): Flow<String> = flow {
logThread("Builder di Flow avviato") // Funziona sul primo `flowOn` specificato
emit("A")
emit("B")
}.map {
logThread("Mappando $it") // Funziona sul secondo `flowOn` specificato
it.toLowerCase()
}.flowOn(Dispatchers.Default) // Il secondo `flowOn` influisce su map() e sul builder di flow
.filter {
logThread("Filtrando $it") // Funziona sul thread da cui viene chiamato collect (di default main/runBlocking)
true
}.flowOn(Dispatchers.IO) // Il primo `flowOn` influisce su map() e sul builder di flow
fun main() = runBlocking {
simpleFlowWithMultipleFlowOn().collect { value ->
logThread("Raccolto $value") // Funziona sul thread runBlocking (main)
}
}
fun logThread(msg: String) {
println("[$msg] [${Thread.currentThread().name}]")
}
In questo esempio:
- Il
flowbuilder emapfunzionano suDispatchers.Default(perché è l'ultimoflowOnnella catena prima di loro). filterfunziona sul thread da cui viene chiamatocollect, cioè sul thread in cui viene eseguitorunBlocking(di solito Main in Android).
È importante capire che flowOn crea un buffer intermedio e non è un "cambio di thread trasparente".