Cold Flow mit shareIn und stateIn in Hot Flow umwandeln
Wandeln Sie Cold Flows mit Sharing-Operatoren in Hot Streams um.
Cold Flow mit shareIn und stateIn in Hot Flow umwandeln ist eine kostenlose Kotlin Academy-Lektion auf CoddyKit. Dies ist Lektion 3 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.
Cold Flows vs. Hot Flows
Cold Flows werden für jeden Collector neu gestartet, während Hot Flows ein gemeinsames Upstream-Abonnement verwenden. Die Umwandlung eines Cold Flows in einen Hot Flow verhindert redundante Arbeit, wenn mehrere Collector abonnieren.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun expensiveFlow() = flow {
println("Starting upstream work") // runs once if shared
repeat(3) { delay(100); emit(it) }
}
fun main() = runBlocking {
val cold = expensiveFlow()
// Two collectors = two executions:
launch { cold.collect { } }
launch { cold.collect { } }
delay(500)
coroutineContext.cancelChildren()
}Grundlagen von shareIn
flow.shareIn(scope, started, replay) wandelt einen Cold Flow in einen SharedFlow um und teilt ein gemeinsames Upstream-Abonnement.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
val cold = flow {
println("Upstream started once")
repeat(5) { delay(100); emit(it) }
}
val hot = cold.shareIn(this, SharingStarted.Eagerly, replay = 0)
launch { hot.collect { println("A: $it") } }
launch { hot.collect { println("B: $it") } }
delay(600)
coroutineContext.cancelChildren()
}Grundlagen von stateIn
flow.stateIn(scope, started, initialValue) wandelt einen Flow in einen StateFlow um – dieser hat immer einen Wert und gibt 1 Wert erneut aus.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
val cold = flow { delay(100); emit(42) }
val state: StateFlow<Int> = cold.stateIn(
scope = this,
started = SharingStarted.Eagerly,
initialValue = 0
)
println(state.value) // 0 immediately
delay(200)
println(state.value) // 42 after upstream emits
coroutineContext.cancelChildren()
}SharingStarted.Eagerly
Eagerly: Der Upstream startet sofort, wenn shareIn/stateIn aufgerufen wird, unabhängig von den Abonnenten.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
val flow = flow {
println("Eagerly started")
emit(1)
}.shareIn(this, SharingStarted.Eagerly)
// Upstream already running even before any collect
delay(50)
launch { flow.collect { println(it) } }
delay(100)
coroutineContext.cancelChildren()
}SharingStarted.Lazily
Lazily: Der Upstream startet beim ersten Abonnenten und wird nie beendet, selbst wenn keine Abonnenten mehr vorhanden sind.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
val flow = flow {
println("Lazily started on first subscriber")
repeat(3) { delay(100); emit(it) }
}.shareIn(this, SharingStarted.Lazily, replay = 1)
delay(50) // no subscriber yet — not started
launch { flow.collect { println(it) } } // triggers start
delay(400)
coroutineContext.cancelChildren()
}SharingStarted.WhileSubscribed
WhileSubscribed(stopTimeout): Der Upstream startet, wenn der erste Abonnent hinzukommt, und stoppt stopTimeout ms, nachdem der letzte Abonnent gegangen ist. Ideal für ViewModels.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
val flow = flow {
println("Started")
repeat(10) { delay(100); emit(it) }
}.shareIn(this, SharingStarted.WhileSubscribed(500))
val job = launch { flow.collect { print("$it ") } }
delay(300)
job.cancel() // subscriber left
delay(200) // within 500ms stop timeout — still running
launch { flow.collect { print("resume $it ") } }
delay(500)
coroutineContext.cancelChildren()
}Typisches ViewModel-Muster
Wandeln Sie in Android-ViewModels Repository-Flows mit stateIn(viewModelScope, WhileSubscribed(5000), initialValue) um, damit sie geteilt werden und Konfigurationsänderungen überstehen.
import kotlinx.coroutines.flow.*
// In ViewModel:
// val uiState: StateFlow<UiState> = repository
// .dataFlow()
// .map { UiState.Success(it) }
// .stateIn(
// scope = viewModelScope,
// started = SharingStarted.WhileSubscribed(5_000),
// initialValue = UiState.Loading
// )
fun main() { println("WhileSubscribed(5000) is the recommended ViewModel pattern") }shareIn vs. stateIn
shareIn → SharedFlow (kein aktueller Wert, konfigurierbares Replay). stateIn → StateFlow (hat immer einen Wert, replay=1). Wählen Sie abhängig davon, ob die Verbraucher einen aktuellen Zustand benötigen.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
val cold = (1..3).asFlow().map { it * 10 }
// SharedFlow — no initial value:
val shared: SharedFlow<Int> = cold.shareIn(this, SharingStarted.Eagerly, replay = 1)
// StateFlow — always has a value:
val state: StateFlow<Int> = cold.stateIn(this, SharingStarted.Eagerly, 0)
delay(100)
println("shared cache: ${shared.replayCache}")
println("state value: ${state.value}")
coroutineContext.cancelChildren()
}Abwägungen beim Replay-Cache
Ein höherer replay-Wert bedeutet, dass späte Abonnenten mehr Verlauf sehen, aber auch mehr Speicher verwendet wird. Für UI-Zustände genügt replay=1 (stateIn). Für Ereignisprotokolle kann ein höherer replay-Wert erforderlich sein.
import kotlinx.coroutines.flow.*
// replay=0: no history, only future events
// replay=1: last value (equivalent to stateIn)
// replay=N: last N events — use for message feeds, logs
// Trade-off: memory vs subscriber freshness
fun main() { println("Choose replay based on late-subscriber requirements") }Risiko nicht geteilter Flows
Ohne Sharing führt jeder Compose-Collector oder ViewModel-Beobachter den Upstream erneut aus – mit redundanten Netzwerkanfragen und Datenbankabfragen. Teilen Sie ressourcenintensive Flows immer.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun expensiveApi() = flow {
println("API CALL") // without sharing: once per collector
emit("data")
}
fun main() = runBlocking {
val shared = expensiveApi().shareIn(this, SharingStarted.Lazily, replay = 1)
launch { shared.collect { } } // one API call, shared
launch { shared.collect { } } // same emission
delay(200)
coroutineContext.cancelChildren()
}Ressourcenbereinigung beim Teilen
Wenn der Scope des Shared Flows abgebrochen wird, wird der Upstream Flow abgebrochen und seine finally-Blöcke werden ausgeführt – Ressourcen werden ordnungsgemäß bereinigt.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun resourceFlow() = flow {
try { repeat(10) { delay(100); emit(it) } }
finally { println("Upstream cleaned up") }
}
fun main() = runBlocking {
val scope = CoroutineScope(SupervisorJob())
val shared = resourceFlow().shareIn(scope, SharingStarted.Eagerly)
launch { shared.collect { print("$it ") } }
delay(250)
scope.cancel() // upstream cleanup runs
delay(100)
}Kurzer Check
Welche SharingStarted-Strategie wird für Android-ViewModels empfohlen?
Zusammenfassung
shareIn wandelt in einen SharedFlow um, stateIn in einen StateFlow. Verwenden Sie WhileSubscribed in ViewModels, um Ressourcen zu sparen. Sharing verhindert redundante Upstream-Ausführungen, wenn mehrere Collector abonnieren.
Häufig gestellte Fragen
Ist die Lektion „Cold Flow mit shareIn und stateIn in Hot Flow umwandeln“ kostenlos?
Ja — der vollständige Text von „Cold Flow mit shareIn und stateIn in Hot Flow umwandeln“ 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 „Cold Flow mit shareIn und stateIn in Hot Flow umwandeln“?
Wandeln Sie Cold Flows mit Sharing-Operatoren in Hot Streams um. 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 3 von 4.
Wie lange dauert die Lektion „Cold Flow mit shareIn und stateIn in Hot Flow umwandeln“?
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
- StateFlow: reaktiver Zustandscontainer für die UI
- SharedFlow: Event-Busse und einmalige Events
- Cold Flow mit shareIn und stateIn in Hot Flow umwandeln
- StateFlow und SharedFlow mit Turbine testen