StateFlow
und SharedFlow
sind Flow APIs
mit denen Datenflüsse optimal Statusaktualisierungen und Werte an mehrere
Verbraucher:innen.
StateFlow
StateFlow
ist ein für State Owners beobachtbarer Ablauf, der den aktuellen und neuen Zustand ausgibt.
an seine Collectors. Der aktuelle Statuswert kann auch über die
value
Property. Um den Status zu aktualisieren und an den Ablauf zu senden, weisen Sie dem
das Attribut value
des
Klasse MutableStateFlow
.
In Android eignet sich StateFlow
hervorragend für Kurse, bei denen
einen beobachtbaren änderbaren Zustand.
In den Beispielen aus Kotlin-Abläufen wird ein StateFlow
kann aus der LatestNewsViewModel
bereitgestellt werden, damit die View
Auf Aktualisierungen des UI-Status warten und den Bildschirmstatus dauerhaft beibehalten
Konfigurationsänderungen.
class LatestNewsViewModel(
private val newsRepository: NewsRepository
) : ViewModel() {
// Backing property to avoid state updates from other classes
private val _uiState = MutableStateFlow(LatestNewsUiState.Success(emptyList()))
// The UI collects from this StateFlow to get its state updates
val uiState: StateFlow<LatestNewsUiState> = _uiState
init {
viewModelScope.launch {
newsRepository.favoriteLatestNews
// Update View with the latest favorite news
// Writes to the value property of MutableStateFlow,
// adding a new element to the flow and updating all
// of its collectors
.collect { favoriteNews ->
_uiState.value = LatestNewsUiState.Success(favoriteNews)
}
}
}
}
// Represents different states for the LatestNews screen
sealed class LatestNewsUiState {
data class Success(val news: List<ArticleHeadline>): LatestNewsUiState()
data class Error(val exception: Throwable): LatestNewsUiState()
}
Die Klasse, die für die Aktualisierung einer MutableStateFlow
verantwortlich ist, ist der Ersteller.
und alle Klassen, die in den StateFlow
gesammelt werden, sind die Verbraucher. „Mag ich“-Bewertung entfernen
Ein Cold-Ablauf, der mit dem flow
-Builder erstellt wurde, ist ein StateFlow
heiß:
die Daten aus dem Ablauf erfassen, löst keinen Producer-Code aus. Ein StateFlow
ist immer aktiv und im Arbeitsspeicher, und es wird in den Papierkorb verschoben.
nur dann erfasst werden, wenn es keine weiteren Verweise von einem automatischen Speicher
Collection-Stamm.
Wenn ein neuer Nutzer beginnt, Daten aus dem Ablauf zu erfassen, erhält er die letzte
im Stream und in allen nachfolgenden
Zuständen angezeigt. Sie finden dieses Verhalten
in anderen beobachtbaren Klassen wie
LiveData
View
wartet wie jeder andere Ablauf auf StateFlow
:
class LatestNewsActivity : AppCompatActivity() {
private val latestNewsViewModel = // getViewModel()
override fun onCreate(savedInstanceState: Bundle?) {
...
// Start a coroutine in the lifecycle scope
lifecycleScope.launch {
// repeatOnLifecycle launches the block in a new coroutine every time the
// lifecycle is in the STARTED state (or above) and cancels it when it's STOPPED.
repeatOnLifecycle(Lifecycle.State.STARTED) {
// Trigger the flow and start listening for values.
// Note that this happens when lifecycle is STARTED and stops
// collecting when the lifecycle is STOPPED
latestNewsViewModel.uiState.collect { uiState ->
// New value received
when (uiState) {
is LatestNewsUiState.Success -> showFavoriteNews(uiState.news)
is LatestNewsUiState.Error -> showError(uiState.exception)
}
}
}
}
}
}
Verwenden Sie zum Konvertieren eines Ablaufs in einen StateFlow
die Methode
stateIn
den Zwischenoperator.
StateFlow, Flow und LiveData
Für StateFlow
und LiveData
wurden
Gemeinsamkeiten. Beide sind beobachtbare Dateninhaberklassen und
in Ihrer App-Architektur
nach einem ähnlichen Muster.
Beachten Sie jedoch, dass StateFlow
und
LiveData
verhält sich anders:
- Für
StateFlow
muss ein Anfangszustand an den Konstruktor übergeben werden.LiveData
hingegen nicht. LiveData.observe()
hebt die Registrierung des Nutzers automatisch auf, wenn der imSTOPPED
-Status, während die Erfassung aus einemStateFlow
- oder die Erfassung durch einen anderen Ablauf nicht automatisch beendet. Um das zu erreichen, müssen Sie den Ablauf aus einemLifecycle.repeatOnLifecycle
-Objekt blockieren.
Kalte Ströme mit shareIn
heiß werden
StateFlow
ist ein heißer Ablauf. Er verbleibt im Arbeitsspeicher, solange er
oder während andere Verweise darauf aus einer automatischen Speicherbereinigung vorhanden sind
Stamm. Sie können kalte Ströme mithilfe der
shareIn
.
callbackFlow
, die in Kotlin-Abläufen erstellt wurde, als
Anstatt für jeden Collector einen neuen Ablauf zu erstellen, können Sie
die aus Firestore zwischen Collectors abgerufenen Daten mithilfe von shareIn
.
Sie müssen Folgendes übergeben:
- Ein
CoroutineScope
, der zum Freigeben des Ablaufs verwendet wird. Dieser Bereich sollte länger als jeder andere Nutzer, um den gemeinsamen Ablauf so lange wie nötig am Laufen zu halten. - Die Anzahl der Objekte, die für jeden neuen Collector wiederholt werden sollen.
- Die Richtlinie für das Startverhalten.
class NewsRemoteDataSource(...,
private val externalScope: CoroutineScope,
) {
val latestNews: Flow<List<ArticleHeadline>> = flow {
...
}.shareIn(
externalScope,
replay = 1,
started = SharingStarted.WhileSubscribed()
)
}
In diesem Beispiel wiederholt der latestNews
-Ablauf das letzte ausgegebene Element noch einmal
an einen neuen Collector und bleibt aktiv, solange externalScope
und es gibt aktive Sammler. Das SharingStarted.WhileSubscribed()
Startrichtlinie sorgt dafür, dass der Upstream-Ersteller aktiv bleibt, solange aktiv sind.
Abonnenten. Es sind auch andere Startrichtlinien verfügbar, z. B.
SharingStarted.Eagerly
, um den Produzenten sofort zu starten, oder
SharingStarted.Lazily
, um mit dem Teilen zu beginnen, nachdem der erste Abonnent angezeigt wurde
und dafür sorgen, dass der Fluss
für immer aktiv bleibt.
SharedFlow
Die Funktion shareIn
gibt einen SharedFlow
zurück, einen Hot Flow, der Werte ausgibt.
die Daten erheben. Ein SharedFlow
ist eine
hoch konfigurierbare Generalisierung von StateFlow
Sie können ein SharedFlow
erstellen, ohne shareIn
zu verwenden. Zum Beispiel haben Sie
Sie könnten einen SharedFlow
verwenden, um Ticks an den Rest der App zu senden, sodass
werden alle Inhalte regelmäßig
gleichzeitig aktualisiert. Abgesehen von
um die neuesten Nachrichten abzurufen, sollten Sie den Nutzer
Informationsbereich mit seiner Sammlung der beliebtesten Themen. Im Folgenden
Code-Snippet zeigt ein TickHandler
ein SharedFlow
frei, sodass andere
wissen, wann der Inhalt aktualisiert werden soll. Verwenden Sie wie bei StateFlow
einen
Sicherungsattribut des Typs MutableSharedFlow
in einer Klasse, um Elemente zu senden
zum Ablauf hinzufügen:
// Class that centralizes when the content of the app needs to be refreshed
class TickHandler(
private val externalScope: CoroutineScope,
private val tickIntervalMs: Long = 5000
) {
// Backing property to avoid flow emissions from other classes
private val _tickFlow = MutableSharedFlow<Unit>(replay = 0)
val tickFlow: SharedFlow<Event<String>> = _tickFlow
init {
externalScope.launch {
while(true) {
_tickFlow.emit(Unit)
delay(tickIntervalMs)
}
}
}
}
class NewsRepository(
...,
private val tickHandler: TickHandler,
private val externalScope: CoroutineScope
) {
init {
externalScope.launch {
// Listen for tick updates
tickHandler.tickFlow.collect {
refreshLatestNews()
}
}
}
suspend fun refreshLatestNews() { ... }
...
}
Sie können das Verhalten von SharedFlow
so anpassen:
- Mit
replay
können Sie eine Anzahl zuvor ausgegebener Werte für neue Abonnenten. - Mit
onBufferOverflow
können Sie eine Richtlinie für den Zeitpunkt des Zwischenspeichers angeben ist voll mit zu sendenden Artikeln. Der Standardwert istBufferOverflow.SUSPEND
. wodurch der Aufrufer gesperrt wird. Weitere Optionen sindDROP_LATEST
oderDROP_OLDEST
.
MutableSharedFlow
hat auch ein subscriptionCount
-Attribut, das Folgendes enthält:
Anzahl der aktiven Collectors, damit Sie Ihr Geschäft optimieren können
entsprechend anpassen. MutableSharedFlow
enthält auch einen resetReplayCache
, wenn Sie die neuesten an den Ablauf gesendeten Informationen nicht noch einmal wiedergeben möchten.
Zusätzliche Ablaufressourcen
- Kotlin-Abläufe unter Android
- Kotlin-Datenflüsse unter Android testen
- Wissenswertes zu den ShareIn- und stateIn-Operatoren von Flow
- Migration von LiveData zu Kotlin-Datenfluss
- Zusätzliche Ressourcen für Kotlin-Koroutinen und -Ablauf