0Pricing
Kotlin Academy · Lezione

combine e zip: unire più Flow

Combini più Flow e ne unisca le emissioni con zip.

combine e zip: unire più Flow è una lezione Kotlin Academy gratuita su CoddyKit. Questa è la lezione 3 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Kotlin Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Kotlin Academy include 4 lezioni in totale.

Perché unire i flussi?

Nelle app reali è spesso necessario combinare più flussi di dati: preferenze dell'utente + dati di rete, campi del modulo + stato della convalida. Kotlin Flow fornisce zip, combine e merge per questo scopo.

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
    val names = flowOf("Alice", "Bob", "Carol")
    val ages  = flowOf(30, 25, 35)
    names.zip(ages) { name, age -> "$name is $age" }
         .collect { println(it) }
}

zip: emissioni abbinate

zip abbina le emissioni una a una e nell'ordine in cui vengono prodotte. Si arresta quando termina il flusso più breve.

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
    val a = flowOf(1, 2, 3, 4)   // 4 elements
    val b = flowOf("a", "b", "c")  // 3 elements — zip stops here
    a.zip(b) { n, s -> "$n-$s" }
     .collect { println(it) } // 1-a, 2-b, 3-c
}

combine: valori più recenti

combine emette un nuovo valore ogni volta che viene emesso un valore da uno qualsiasi dei flussi, utilizzando il valore più recente di ciascuno. Entrambi i flussi devono aver emesso almeno un valore.

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
    val flow1 = MutableStateFlow(1)
    val flow2 = MutableStateFlow("a")
    combine(flow1, flow2) { n, s -> "$n-$s" }
        .take(1)
        .collect { println(it) } // 1-a
}

Differenza tra combine e zip

zip: attende la coppia corrispondente. combine: si attiva a ogni aggiornamento utilizzando i valori più recenti. Utilizzi combine per interfacce reattive (ad esempio, due campi di un modulo) e zip per abbinamenti sequenziali.

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
    // zip: 1-a, 2-b
    val nums = flowOf(1, 2).zip(flowOf("a", "b")) { n, s -> "$n-$s" }
    nums.collect { println("zip: $it") }

    // combine fires more:
    combine(flowOf(1, 2), flowOf("a")) { n, s -> "$n-$s" }
        .collect { println("combine: $it") }
}

merge: flussi intercalati

merge emette i valori di più flussi man mano che arrivano, senza abbinarli: l'ordine di output dipende dalla tempistica delle emissioni.

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
    val a = flow { emit("A1"); delay(50); emit("A2") }
    val b = flow { delay(25); emit("B1") }
    merge(a, b).collect { println(it) } // A1, B1, A2
}

combine con 3 o più flussi

combine supporta più flussi. Li passi come vararg e la lambda riceve tutti i valori più recenti.

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
    val a = MutableStateFlow("hello")
    val b = MutableStateFlow(42)
    val c = MutableStateFlow(true)
    combine(a, b, c) { s, n, flag -> "$s-$n-$flag" }
        .take(1)
        .collect { println(it) } // hello-42-true
}

flatMapMerge: flussi interni concorrenti

flatMapMerge associa ogni elemento a un flusso e raccoglie tutti i flussi interni in modo concorrente, unificandone gli output.

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
    (1..3).asFlow()
        .flatMapMerge { n ->
            flow { delay(100L - n * 10); emit("result-$n") }
        }
        .collect { println(it) }
}

flatMapLatest: annullamento alla nuova emissione

flatMapLatest annulla il flusso interno corrente quando arriva un nuovo elemento upstream: è perfetto per la ricerca durante la digitazione.

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
    flowOf("k", "ko", "kot", "kotl", "kotli", "kotlin")
        .flatMapLatest { query ->
            flow {
                delay(50)  // simulate debounced search
                emit("Result for: $query")
            }
        }
        .collect { println(it) } // only "Result for: kotlin"
}

zip per abbinare transazioni

Utilizzi zip per abbinare gli eventi provenienti da due flussi: ad esempio, le azioni dell'utente con le conferme del server, garantendo una corrispondenza uno a uno.

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
    val orders = flowOf("Order1", "Order2", "Order3")
    val confirmations = flowOf("Confirmed", "Confirmed", "Rejected")
    orders.zip(confirmations) { order, status -> "$order: $status" }
          .collect { println(it) }
}

combine per la convalida dei moduli

Combini i flussi di nome utente e password per calcolare in modo reattivo la validità del modulo: il risultato viene aggiornato ogni volta che cambia uno dei due campi.

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
    val username = MutableStateFlow("")
    val password = MutableStateFlow("")
    val isValid = combine(username, password) { u, p ->
        u.length >= 3 && p.length >= 8
    }
    username.value = "alice"
    password.value = "secure123"
    println(isValid.first()) // true
}

onEach + combine per il caricamento da più origini

Combini un flag di caricamento con un flusso di dati per produrre un unico oggetto di stato dell'interfaccia a partire da più origini indipendenti.

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
data class UI(val loading: Boolean, val data: String)
fun main() = runBlocking {
    val loading = MutableStateFlow(true)
    val data    = MutableStateFlow("")
    combine(loading, data) { l, d -> UI(l, d) }
        .take(2)
        .collect { println(it) }
    data.value = "result"
    loading.value = false
}

Controllo rapido

Qual è la differenza principale tra zip e combine?

Riepilogo

zip abbina le emissioni in sequenza; combine si attiva a ogni aggiornamento utilizzando i valori più recenti; merge intercala flussi indipendenti; flatMapLatest annulla i flussi interni non più aggiornati. Scelga in base alla necessità di abbinamento o reattività.

Domande Frequenti

La lezione «combine e zip: unire più Flow» è gratuita?

Sì — il testo completo di «combine e zip: unire più Flow» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Kotlin Academy, passa a CoddyKit PRO. Il corso Kotlin Academy include 4 lezioni in totale.

Cosa imparerò in «combine e zip: unire più Flow»?

Combini più Flow e ne unisca le emissioni con zip. Eserciti Kotlin Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare Kotlin Academy?

Non è richiesta alcuna esperienza precedente. Kotlin Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 3 di 4.

Quanto tempo richiede la lezione «combine e zip: unire più Flow»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione Kotlin Academy?

Sì. Ogni lezione Kotlin Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Operatori di Flow: map, filter, transform e take
  2. catch e onCompletion: gestione degli errori in Flow
  3. combine e zip: unire più Flow
  4. flowOn e buffer: contesto e backpressure
← Torna a Kotlin Academy