0Pricing
Kotlin Academy · Lekcja

SharedFlow: magistrale zdarzeń i zdarzenia jednorazowe

Konfiguruj replay i extraBufferCapacity w SharedFlow do rozgłaszania zdarzeń.

SharedFlow: magistrale zdarzeń i zdarzenia jednorazowe to bezpłatna lekcja Kotlin Academy na CoddyKit. To lekcja 2 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Kotlin Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Kotlin Academy zawiera 4 lekcji w sumie.

Czym jest SharedFlow?

SharedFlow to gorący obiekt Flow, który rozgłasza wartości do wszystkich aktywnych kolektorów. W przeciwieństwie do StateFlow nie ma pojęcia bieżącej wartości — jest przeznaczony wyłącznie do obsługi zdarzeń.

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()
}

Parametr replay

replay buforuje ostatnie N emisji. Nowi kolektorzy natychmiast otrzymują do N wcześniejszych zdarzeń. Wartość domyślna to 0 (brak powtórnych emisji).

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 dodaje miejsce w buforze poza pamięcią replay. Nadawcy mogą emitować bez zawieszania do momentu zapełnienia bufora.

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 do emisji bez zawieszania

tryEmit(value) emituje bez zawieszania, zwracając false, jeśli bufor jest pełny. Należy używać go w kontekstach nieoznaczonych jako suspend, takich jak callbacki i procedury obsługi kliknięć.

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()
}

Zdarzenia jednorazowe (nawigacja UI)

Należy używać SharedFlow z replay=0 do jednorazowych zdarzeń interfejsu, takich jak nawigacja lub wyświetlanie Snackbar — zdarzenia nie są powtarzane podczas ponownej kompozycji.

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 a StateFlow

StateFlow: stan z bieżącą wartością (stan interfejsu). SharedFlow: zdarzenia bez trwałego przechowywania (nawigacja, Snackbar, analityka). Należy wybrać odpowiedni typ w zależności od tego, czy odbiorcy potrzebują najnowszej wartości.

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") }

Magistrala zdarzeń z użyciem SharedFlow

Należy zaimplementować prostą magistralę zdarzeń dla całej aplikacji za pomocą singletonu SharedFlow, zastępując wzorce z RxJava PublishSubject.

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 to obiekt StateFlow śledzący liczbę aktywnych kolektorów — przydatny do uruchamiania i zatrzymywania producentów nadrzędnego przepływu.

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() czyści bufor replay, co jest przydatne, gdy powtarzane zdarzenia są nieaktualne i nowi subskrybenci nie powinni ich widzieć.

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}")  // []
}

Obsługa backpressure w SharedFlow

Gdy odbiorcy działają wolno, użyj onBufferOverflow, aby wybrać: SUSPEND (domyślnie), DROP_OLDEST lub 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()
}

Zbieranie z limitem czasu

Zbieraj dane z SharedFlow z limitem czasu, aby przetworzyć skończoną liczbę zdarzeń, a następnie zakończyć działanie — przydatne w testach lub przetwarzaniu o ograniczonym zakresie.

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")
}

Szybkie sprawdzenie

Jakiej wartości replay należy użyć dla jednorazowych zdarzeń interfejsu użytkownika, takich jak nawigacja?

Podsumowanie

SharedFlow to gorący rozgłaszacz zdarzeń. Użyj replay=0 dla zdarzeń jednorazowych oraz replay>0 dla odbiorców dołączających z opóźnieniem. Używaj tryEmit w kontekstach, które nie obsługują zawieszania. Wybierz SharedFlow dla zdarzeń, a StateFlow dla stanu.

Często zadawane pytania

Czy lekcja „SharedFlow: magistrale zdarzeń i zdarzenia jednorazowe” jest bezpłatna?

Tak — pełny tekst „SharedFlow: magistrale zdarzeń i zdarzenia jednorazowe” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Kotlin Academy, przejdź na CoddyKit PRO. Kurs Kotlin Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „SharedFlow: magistrale zdarzeń i zdarzenia jednorazowe”?

Konfiguruj replay i extraBufferCapacity w SharedFlow do rozgłaszania zdarzeń. Ćwiczysz Kotlin Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć Kotlin Academy?

Nie wymagamy żadnego doświadczenia. Kotlin Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 2 z 4.

Ile czasu zajmuje lekcja „SharedFlow: magistrale zdarzeń i zdarzenia jednorazowe”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji Kotlin Academy?

Tak. Każda lekcja Kotlin Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. StateFlow: gorący kontener stanu dla interfejsu
  2. SharedFlow: magistrale zdarzeń i zdarzenia jednorazowe
  3. Konwersja zimnego Flow na gorący za pomocą shareIn i stateIn
  4. Testowanie StateFlow i SharedFlow z Turbine
← Powrót do Kotlin Academy