0Pricing
Kotlin Academy · Lektion

SharedFlow: Event-Busse und einmalige Events

Konfigurieren Sie replay und extraBufferCapacity von SharedFlow für die Übertragung von Events.

SharedFlow: Event-Busse und einmalige Events ist eine kostenlose Kotlin Academy-Lektion auf CoddyKit. Dies ist Lektion 2 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Kotlin Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Kotlin Academy-Kurs umfasst insgesamt 4 Lektionen.

Was ist SharedFlow?

SharedFlow ist ein heißer Flow, der Daten an alle aktiven Collector sendet. Anders als StateFlow kennt er keinen aktuellen Wert – er ist ausschließlich ereignisgesteuert.

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
    val events = MutableSharedFlow<String>()
    launch { events.collect { println("Collector 1: $it") } }
    launch { events.collect { println("Collector 2: $it") } }
    delay(50)
    events.emit("UserLoggedIn")
    events.emit("DataRefreshed")
    delay(50)
    coroutineContext.cancelChildren()
}

Der replay-Parameter

replay puffert die letzten N Ausgaben. Neue Collector erhalten sofort bis zu N vergangene Ereignisse. Der Standardwert ist 0 (keine Wiederholung).

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
    val flow = MutableSharedFlow<Int>(replay = 2)
    flow.emit(1); flow.emit(2); flow.emit(3)
    // Late subscriber gets last 2:
    flow.collect { print("$it ") }  // prints 2 3
}

extraBufferCapacity

extraBufferCapacity fügt zusätzlich zum Replay weiteren Pufferplatz hinzu. Sender können Ausgaben erzeugen, ohne zu suspendieren, bis der Puffer voll ist.

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
    val flow = MutableSharedFlow<Int>(
        replay = 0,
        extraBufferCapacity = 10
    )
    // Can emit up to 10 times without a collector ready:
    repeat(10) { flow.tryEmit(it) }
    launch { flow.collect { print("$it ") } }
    delay(50)
    coroutineContext.cancelChildren()
}

tryEmit für eine nicht blockierende Ausgabe

tryEmit(value) gibt einen Wert aus, ohne zu suspendieren, und liefert false zurück, wenn der Puffer voll ist. Verwenden Sie es in nicht suspendierenden Kontexten, etwa in Callbacks oder Click-Handlern.

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
    val flow = MutableSharedFlow<String>(extraBufferCapacity = 5)
    val ok = flow.tryEmit("click")  // non-suspending
    println("Emitted: $ok")
    launch { flow.collect { println(it) } }
    delay(50)
    coroutineContext.cancelChildren()
}

Einmalige Ereignisse (UI-Navigation)

Verwenden Sie SharedFlow mit replay=0 für einmalige UI-Ereignisse wie Navigation oder das Anzeigen einer Snackbar – Ereignisse werden bei einer Neuzusammensetzung nicht erneut ausgegeben.

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
class NavViewModel {
    private val _events = MutableSharedFlow<String>()
    val events = _events.asSharedFlow()
    fun navigateTo(route: String) {
        // viewModelScope.launch:
        kotlinx.coroutines.GlobalScope.launch { _events.emit(route) }
    }
}
// Collect in UI:
// viewModel.events.collect { route -> navController.navigate(route) }

SharedFlow im Vergleich zu StateFlow

StateFlow: Zustand mit aktuellem Wert (UI-Zustand). SharedFlow: Ereignisse ohne Persistenz (Navigation, Snackbar, Analytics). Wählen Sie abhängig davon, ob die Konsumenten den neuesten Wert benötigen.

import kotlinx.coroutines.flow.*
// StateFlow: always has a value; new subscribers get current value
val uiState = MutableStateFlow("idle")

// SharedFlow: no stored value; events fire and are gone (unless replay>0)
val singleEvents = MutableSharedFlow<String>(replay = 0)

fun main() { println("State = what it is; Event = what happened") }

Event-Bus mit SharedFlow

Implementieren Sie mit einem Singleton-SharedFlow einen einfachen app-weiten Event-Bus, der PublishSubject-Muster von RxJava ersetzt.

import kotlinx.coroutines.flow.*
object EventBus {
    private val _events = MutableSharedFlow<Any>(extraBufferCapacity = 100)
    val events = _events.asSharedFlow()
    fun post(event: Any) { _events.tryEmit(event) }
}
sealed class AppEvent {
    object UserLoggedOut : AppEvent()
    data class ShowError(val msg: String) : AppEvent()
}
// Usage: EventBus.post(AppEvent.UserLoggedOut)

subscriptionCount

sharedFlow.subscriptionCount ist ein StateFlow, der die Anzahl aktiver Collector verfolgt – nützlich zum Starten und Stoppen vorgelagerter Produzenten.

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
    val flow = MutableSharedFlow<Int>()
    println("Subscribers: ${flow.subscriptionCount.value}")  // 0
    val job = launch { flow.collect { } }
    delay(50)
    println("Subscribers: ${flow.subscriptionCount.value}")  // 1
    job.cancel()
    delay(50)
    println("Subscribers: ${flow.subscriptionCount.value}")  // 0
}

resetReplayCache

resetReplayCache() leert den gepufferten Replay-Cache. Das ist nützlich, wenn die wiedergegebenen Ereignisse veraltet sind und neue Abonnenten sie nicht sehen sollen.

import kotlinx.coroutines.flow.*
fun main() {
    val flow = MutableSharedFlow<Int>(replay = 3)
    flow.tryEmit(1); flow.tryEmit(2); flow.tryEmit(3)
    println("Replay cache: ${flow.replayCache}")  // [1, 2, 3]
    flow.resetReplayCache()
    println("Replay cache: ${flow.replayCache}")  // []
}

Umgang mit Backpressure in SharedFlow

Wenn Collector langsam sind, verwenden Sie onBufferOverflow, um zwischen folgenden Optionen zu wählen: SUSPEND (Standard), DROP_OLDEST oder DROP_LATEST.

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.channels.BufferOverflow
fun main() = runBlocking {
    val flow = MutableSharedFlow<Int>(
        replay = 0,
        extraBufferCapacity = 3,
        onBufferOverflow = BufferOverflow.DROP_OLDEST
    )
    repeat(10) { flow.tryEmit(it) }
    launch {
        flow.collect { println(it) }  // only sees most recent 3
    }
    delay(50)
    coroutineContext.cancelChildren()
}

Mit Timeout sammeln

Sammeln Sie einen SharedFlow mit einem Timeout, um eine begrenzte Anzahl von Ereignissen zu verarbeiten und anschließend zu stoppen – nützlich für Tests oder eine begrenzte Verarbeitung.

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
    val events = MutableSharedFlow<String>()
    launch { repeat(5) { delay(50); events.emit("Event $it") } }
    withTimeoutOrNull(200) {
        events.collect { println(it) }
    }
    println("Done collecting")
}

Kurzer Check

Welchen Wert für replay sollten Sie für einmalige UI-Ereignisse wie Navigation verwenden?

Zusammenfassung

SharedFlow ist ein Hot-Broadcaster für Ereignisse. Verwenden Sie replay=0 für einmalige Ereignisse und replay>0 für späte Abonnenten. Verwenden Sie tryEmit in nicht-suspendierenden Kontexten. Wählen Sie SharedFlow für Ereignisse und StateFlow für Zustände.

Häufig gestellte Fragen

Ist die Lektion „SharedFlow: Event-Busse und einmalige Events“ kostenlos?

Ja — der vollständige Text von „SharedFlow: Event-Busse und einmalige Events“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Kotlin Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Kotlin Academy-Kurs umfasst insgesamt 4 Lektionen.

Was lerne ich in „SharedFlow: Event-Busse und einmalige Events“?

Konfigurieren Sie replay und extraBufferCapacity von SharedFlow für die Übertragung von Events. Du übst Kotlin Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um Kotlin Academy zu starten?

Keine Vorkenntnisse erforderlich. Kotlin Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 2 von 4.

Wie lange dauert die Lektion „SharedFlow: Event-Busse und einmalige Events“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser Kotlin Academy-Lektion Code schreiben und ausführen?

Ja. Jede Kotlin Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. StateFlow: reaktiver Zustandscontainer für die UI
  2. SharedFlow: Event-Busse und einmalige Events
  3. Cold Flow mit shareIn und stateIn in Hot Flow umwandeln
  4. StateFlow und SharedFlow mit Turbine testen
← Zurück zu Kotlin Academy