Middle
Πώς μπορείτε να εναλλάσσετε νημάτια στο Flow; Σε ποιο νήμα λειτουργεί το Flow;
sobes.tech AI
Απάντηση από AI
Κατά την προεπιλογή, το Flow λειτουργεί στο νήμα από το οποίο ξεκίνησε. Μπορείτε να αλλάξετε νήματα χρησιμοποιώντας τον τελεστή flowOn.
import kotlinx.coroutines.CoroutineDispatcher // Για CoroutineDispatcher
import kotlinx.coroutines.Dispatchers // Για Dispatchers
import kotlinx.coroutines.flow.Flow // Για Flow
import kotlinx.coroutines.flow.flow // Για flow
import kotlinx.coroutines.flow.flowOn // Για flowOn
import kotlinx.coroutines.runBlocking // Για runBlocking
// Παράδειγμα λειτουργίας που επιστρέφει ένα Flow
fun simpleFlow(): Flow<Int> = flow {
logThread("Ξεκίνησε το Flow") // Καταγραφή του νήματος όπου ξεκινάει ο builder του flow
for (i in 1..3) {
emit(i) // Εκπομπή τιμών
}
}
fun main() = runBlocking {
simpleFlow()
.flowOn(Dispatchers.IO) // Αλλαγή upstream (εκπομπούς) σε Dispatchers.IO
.collect { value ->
logThread("Συλλεγμένο $value") // Καταγραφή του νήματος όπου συλλέγονται οι τιμές
}
}
// Βοηθητική λειτουργία για καταγραφή νήματος
fun logThread(msg: String) {
println("[$msg] [${Thread.currentThread().name}]")
}
Ο τελεστής flowOn επηρεάζει το νήμα στο οποίο εκτελούνται οι τελεστές πριν από αυτόν στη σειρά (συμπεριλαμβανομένου του flow builder). Οι τελεστές μετά το flowOn εκτελούνται στο νήμα που ορίζεται στο επιχείρημα flowOn. Αν υπάρχουν πολλαπλά flowOn στη σειρά, καθένας επηρεάζει το μέρος της σειράς που προηγείται.
Παράδειγμα με πολλαπλά flowOn:
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.runBlocking
fun simpleFlowWithMultipleFlowOn(): Flow<String> = flow {
logThread("Ξεκίνησε ο builder του Flow") // Θα λειτουργεί στο πρώτο καθορισμένο flowOn
emit("A")
emit("B")
}.map {
logThread("Χαρτογράφηση $it") // Θα λειτουργεί στο δεύτερο καθορισμένο flowOn
it.toLowerCase()
}.flowOn(Dispatchers.Default) // Το δεύτερο flowOn επηρεάζει το map() και τον builder του flow
.filter {
logThread("Φιλτράρισμα $it") // Θα λειτουργεί στο νήμα από το οποίο καλείται το `collect` (κατά κανόνα main/runBlocking)
true
}.flowOn(Dispatchers.IO) // Το πρώτο flowOn επηρεάζει το map() και τον builder του flow
fun main() = runBlocking {
simpleFlowWithMultipleFlowOn().collect { value ->
logThread("Συλλεγμένο $value") // Λειτουργεί στο νήμα runBlocking (main)
}
}
fun logThread(msg: String) {
println("[$msg] [${Thread.currentThread().name}]")
}
Σε αυτό το παράδειγμα:
- Ο builder του
flowκαι τοmapθα λειτουργούν στοDispatchers.Default(επειδή αυτός είναι ο τελευταίοςflowOnστη σειρά πριν από αυτούς). - Το
filterθα λειτουργεί στο νήμα από το οποίο καλείται τοcollect, δηλαδή στο νήμα όπου εκτελείται τοrunBlocking(συνήθως Main στο Android).
Είναι σημαντικό να καταλάβετε ότι το flowOn δημιουργεί ένα ενδιάμεσο buffer και δεν αποτελεί "διαφανή" αλλαγή νήματος.