Vollständiger Leitfaden zu StateFlow und SharedFlow: LiveData auf Android übertreffen

  • Grundlegender Unterschied zwischen kalten (Flow) und heißen (StateFlow und SharedFlow) Datenflüssen für das Datenmanagement.
  • Kriterien für die Wahl zwischen StateFlow für persistente Zustände und SharedFlow für ephemere Ereignisse.
  • Sichere Sammlungsstrategien mit repeatOnLifecycle zur Optimierung des Ressourcenverbrauchs in der Benutzeroberfläche.

StateFlow und SharedFlow: LiveData auf Android übertreffen

Wer sich mit Android beschäftigt, kennt sicherlich das altbekannte Problem der Datenverarbeitung in der Präsentationsschicht. Lange Zeit war LiveData die unangefochtene Nummer eins, doch mit dem Aufkommen von Kotlin-Coroutinen sind deutlich leistungsfähigere und flexiblere Werkzeuge entstanden. Die Rede ist von StateFlow und SharedFlow , die die natürliche Weiterentwicklung für die reaktive und effiziente Verwaltung von Datenflüssen darstellen.

Tatsächlich scheinen die Konzepte zwar auf den ersten Blick ähnlich, verfolgen aber jeweils einen anderen Zweck. Die Anzeige des Newsfeeds soll sich merken, wo dieser zuletzt angezeigt wurde, und gleichzeitig eine kurze Benachrichtigung für eine Toast-Nachricht senden, die nur einmal gelesen werden soll. Um Missverständnisse zu vermeiden, erklären wir im Folgenden die Funktionsweise dieser Hot-Streams und warum Sie LiveData in modernen Projekten besser nicht mehr verwenden sollten.

Das Konzept des Flusses: Kalt oder heiß?

Um StateFlow und SharedFlow zu verstehen, muss man zunächst den Unterschied zwischen einem kalten und einem heißen Flow begreifen. Ein Standard-Flow ist kalt , d. h. er ist wie ein Rezept: Es passiert nichts, bis ihn jemand ausführt (durch den Aufruf von `collect`). Das Problem dabei ist, dass bei drei Abonnenten der Code des Produzenten dreimal ausgeführt wird, was den Akku belasten oder redundante API-Anfragen verursachen kann.

Hier kommen Hot Streams ins Spiel. Sowohl StateFlow als auch SharedFlow sind strategisch Hot Streams , d. h. der Producer bleibt aktiv, unabhängig davon, ob jemand zuhört. Dadurch können mehrere Collector dieselbe Datenquelle nutzen , wodurch verhindert wird, dass die Anwendung dieselbe Arbeit wiederholt ausführt – ein entscheidender Faktor für die Systemstabilität.

StateFlow: Der ideale Ersatz für LiveData

StateFlow ist im Wesentlichen ein Zustandscontainer. Seine Hauptfunktion besteht darin, dass er stets einen aktuellen Wert speichert , der synchron über die `.value`-Eigenschaft abgefragt werden kann. Er eignet sich ideal zur Verwaltung des Zustands der Benutzeroberfläche, beispielsweise um festzustellen, ob ein Bildschirm geladen wird oder ob Profildaten erfolgreich aktualisiert wurden.

Konfiguration und Struktur von Multi-Modul-Projekten in Android Studio
Verwandte Artikel:
Vollständiger Leitfaden zum Einrichten und Strukturieren von Multi-Modul-Projekten in Android Studio

Im Gegensatz zu LiveData benötigt StateFlow einen Initialwert im Konstruktor, wodurch die Unsicherheit durch Nullzustände beim Start vermieden wird. Darüber hinaus implementiert es ein Verhalten zur Zusammenführung und Deduplizierung von Werten : Wird derselbe Wert zweimal hintereinander ausgegeben, ignoriert der Flow ihn einfach. Dies ist ideal, um unnötige Aktualisierungen der Benutzeroberfläche zu verhindern, wenn sich die Daten nicht geändert haben.

Um dies in einem ViewModel zu implementieren, empfiehlt sich die Verwendung einer privaten MutableStateFlow-Fallback-Eigenschaft , die als unveränderlicher StateFlow bereitgestellt wird. Dadurch wird sichergestellt, dass nur das ViewModel den Zustand ändern kann, der unidirektionale Datenfluss eingehalten und eine Manipulation der Daten durch die View verhindert wird.

SharedFlow: Der Ereignisbus für einzigartige Aktionen

StateFlow dient der Zustandsverwaltung, SharedFlow der Ereignisverwaltung. Stellen Sie sich vor, Sie möchten einen Fehlerdialog anzeigen oder zu einem anderen Bildschirm navigieren. Bei Verwendung von StateFlow würde das Drehen des Geräts dazu führen, dass der neue Collector den letzten Wert empfängt und das Ereignis erneut ausgelöst wird – ein schwerwiegender Fehler. SharedFlow behebt dieses Problem, da es mit einem Wiederholungswert von Null konfiguriert werden kann.

Dieser Ablauf ist deutlich flexibler und ermöglicht die Anpassung von Parametern wie dem Überlaufpuffer . Ist der Puffer voll, kann der Sender angehalten oder der älteste bzw. neueste Wert verworfen werden. Ein wesentlicher Vorteil von SharedFlow ist das Senden wiederholter Werte . Muss beispielsweise dieselbe Fehlermeldung „Verbindungsfehler“ dreimal gesendet werden, erledigt SharedFlow dies ohne Zögern, während StateFlow diese Meldungen herausfiltern würde.

Technischer Vergleich: StateFlow vs. SharedFlow vs. LiveData

Um Missverständnisse in technischen Vorstellungsgesprächen oder bei der Architekturplanung zu vermeiden, ist es wichtig, die kritischen Punkte zu beachten. LiveData ist einfach und verwaltet den Lebenszyklus automatisch , ist aber stark an Android gebunden. StateFlow und SharedFlow hingegen, die Teil der Kotlin-Coroutinen sind, sind plattformunabhängig , was Unit-Tests und die Erstellung sauberer Domänenschichten erheblich vereinfacht.

  • StateFlow: Erzwingt einen Anfangswert, hat .value, dedupliziert Werte und ist ideal für UI-Zustände.
  • Gemeinsamer FlussEs benötigt keinen Anfangswert, ist hinsichtlich der Wiedergabe konfigurierbar und ist die richtige Option für kurzlebige Ereignisse.
  • LiveDatenEs benötigt keinen Anfangswert, berücksichtigt den Lebenszyklus, ist aber bei asynchronen Transformationen weniger leistungsfähig.

Die Bedeutung einer sicheren Ernte

Ein häufiger Fehler ist die Ausführung von `collect` innerhalb eines einfachen Coroutine-Scopes in der Activity. Dies ist gefährlich, da die Datenverarbeitung auch dann fortgesetzt wird, wenn die App im Hintergrund läuft , was zu Abstürzen oder übermäßiger CPU-Auslastung führen kann. Die moderne Lösung ist die Verwendung der API `repeatOnLifecycle(Lifecycle.State.STARTED)`.

Diese Funktion bewirkt, dass die Datenerfassung aktiviert wird, sobald die Ansicht sichtbar ist, und automatisch beendet wird, sobald der Status „STOPPED“ erreicht ist . Für Jetpack Compose wird die Verwendung von `collectAsStateWithLifecycle()` empfohlen , da diese Funktion die Logik nativ integriert und so einen effizienten Umgang der Geräteressourcen gewährleistet.

Umwandlung kalter Strömungen in warme Strömungen

Manchmal erhalten wir einen Datenfluss aus einer Datenbank (wie Room) oder einem Repository, der zunächst nicht aktiv ist. Um ihn aktiv zu machen, verwenden wir die Operatoren `stateIn` oder `shareIn` . Diese Operatoren benötigen einen `CoroutineScope` und eine Startstrategie. Die gebräuchlichste ist `SharingStarted.WhileSubscribed(5000)`.

Diese Konfiguration ist genial, da der Stream so lange aktiv bleibt, wie Abonnenten vorhanden sind. Wird der Bildschirm geschlossen, wartet das System fünf Sekunden, bevor der Stream gestoppt wird. Dies ist entscheidend, damit der Stream bei einer Bildschirmdrehung nicht zerstört und neu erstellt wird und somit unnötige Anfragen an den Server oder die lokale Datenbank vermieden werden.

MVI-Architektur in Android
Verwandte Artikel:
Vollständiger Leitfaden zur MVI-Architektur in Android

Die Beherrschung dieser Werkzeuge erfordert das Verständnis, dass Zustände mithilfe von StateFlow persistent gespeichert und dedupliziert werden müssen, während einmalige Aktionen über SharedFlow abgewickelt werden. Durch die Kombination mit Lebenszyklusbewusstsein und der Transformation von Cold Flows mithilfe von stateIn erreichen wir eine robuste, vollständig reaktive Android-Architektur, die für die Performance auf mobilen Geräten im realen Einsatz optimiert ist. Teilen Sie diese Anleitung und helfen Sie anderen, mehr über dieses Thema zu erfahren.


Surfshark Antivirus für Android
Es könnte Sie interessieren:
So entfernen Sie Viren auf Android: Eine vollständige und aktualisierte Anleitung zur Bereinigung Ihres Smartphones
Als bevorzugte Quelle in Google hinzufügen