StreamBuilder — egy Flutter widget, amely automatikusan újraépíti a felületet aszinkron adatfolyamból érkező új adatok fogadásakor. Ellentétben a FutureBuilder-rel, amely egyszeri eredménnyel dolgozik, a StreamBuilder támogatja a folyamatos UI-frissítést a Stream teljes életciklusa alatt. A Flutter hivatalos dokumentációja (2026) szerint a StreamBuilder valós idejű alkalmazásokban használatos: chat-ek, hírcsatornák, érzékelő-felügyelet és pénzügyi tickerek. Ez a reaktív programozás kulcsfontosságú eszköze, ahol a UI kézi setState-hívások nélkül tükrözi az adatok állapotát.
Főbb pontok
StreamBuilder — egy widget a Flutter SDK csomagból, amely feliratkozik egy Stream-re és minden új folyameseménynél újraépíti a gyermek elemét. A StreamBuilder egy Stream objektumot fogad és az utolsó, folyamból kapott snapshot alapján visszaad egy widget-et.
A Flutter architektúrában a StreamBuilder a Builder widget-ek csoportjába tartozik, amelyek elválasztják a UI felépítését az adatok állapotától. Ellentétben a StatefulWidget-dzsel, ahol az állapotváltoztatás explicit setState hívást igényel, a StreamBuilder automatikusan reagál az aszinkron eseményekre, ami egyszerűsíti a kódot és csökkenti a szinkronizációs hibák kockázatát.
Ellentétben a FutureBuilder-rel, amely egyetlen aszinkron értéket dolgoz fel, a StreamBuilder folyamatos adatfolyamokra lett tervezve. A FutureBuilder az első eredmény fogadása után befejezi a munkát, míg a StreamBuilder tovább hallgatja a folyamot és minden új eseménynél frissíti a UI-t.
A StreamBuilder minden olyan forgatókönyvben használatos, ahol az adatok folyamatosan érkeznek: WebSocket kapcsolatok, érzékelő-visszahívások, Firebase értesítések, Bluetooth eseménysorok és alkalmazásállapot sugárzása BLoC-on keresztül. A GitHub-on (2025) található Flutter projektek elemzése szerint a StreamBuilder a három leggyakrabban használt Builder widget közé tartozik a FutureBuilder és LayoutBuilder mellett.
Következtetés: használja a StreamBuilder-t mindenhol, ahol a UI-nak folyamatosan változó adatokat kell tükröznie, elkerülve a kézi állapotkezelést StatefulWidget segítségével.
StreamBuilder feliratkozik a Stream-re az építés pillanatában és leiratkozik a widget megsemmisülésekor. Minden alkalommal, amikor a Stream eseményt bocsát ki, a StreamBuilder egy új AsyncSnapshot-ot kap és meghívja a builder függvényt a UI újraépítéséhez.
A folyamat három szakaszból áll. Első: a StreamBuilder létrehoz egy feliratkozást a kapott Stream-re a stream.listen metóduson keresztül. Második: minden eseménynél a StreamBuilder frissíti a belső AsyncSnapshot-ot és „piszkosnak“ jelöli a widget-et az újraépítéshez. Harmadik: a keretrendszer meghívja a builder függvényt az új snapshot-tal, és a UI megjeleníti az aktuális adatokat.
Fontos: a StreamBuilder belsőleg StreamSubscription-t használ. Ha a Stream közvetlenül kerül átadásra, a StreamBuilder egyszer iratkozik fel az inicializáláskor. Ha a Stream megváltozik (például a szülő újraépítésekor), a StreamBuilder leiratkozik a régi folyamról és feliratkozik az újra. Ezt a viselkedést az initialData és buildWhen paraméterek vezérlik, amelyek lehetővé teszik az újraépítések számának optimalizálását.
Következtetés: a feliratkozás életciklusának megértése a StreamBuilder helyes használatának alapja. A folyamok helytelen kezelése memóriaszivárgáshoz vagy elavult adatokhoz vezet a UI-ban.
Az AsyncSnapshot objektum connectionState tulajdonsága határozza meg, hogy a StreamBuilder a folyammal való munka melyik szakaszában van. Négy állapot különböztethető meg: none, waiting, active, done.
None — a kezdeti állapot, amikor a Stream még nem kezdett el adatokat küldeni. Ebben az állapotban a snapshot.connectionState egyenlő ConnectionState.none, a snapshot.data pedig null. Általában ebben az állapotban egy helyőrző vagy az első eseményre való várakozás jelenik meg. Ha a Stream nem szolgáltat kezdeti adatokat, a StreamBuilder ebből az állapotból indul.
Waiting — az aszinkron folyamtól érkező adatokra várakozás állapota. A Stream aktív, de az adatok még nem érkeztek meg. Ez az állapot például hálózati adatok betöltésekor vagy hosszú életű kapcsolat létesítésekor lép fel. Ebben az állapotban általában CircularProgressIndicator vagy betöltési váz jelenik meg.
Active — a folyam adatokat bocsát ki, és a UI aktuális információkat jelenít meg. Ebben az állapotban a snapshot.hasData true, a snapshot.data pedig a folyam utolsó értékét tartalmazza. Ha a Stream Broadcast Stream, az aktív állapot együtt létezhet az új adatokra várakozással.
Done — a folyam befejeződött, új adatok nem lesznek. A snapshot.data a folyam lezárása előtt átadott utolsó értéket tartalmazza. Ha a folyam sikeresen befejeződött, a snapshot.hasError false. Ezt az állapotot a végeredmény megjelenítésére használják: „Betöltés befejezve“ üzenet vagy áttérés a következő képernyőre.
Következtetés: a StreamBuilder segítségével történő UI-építéskor mind a négy állapotot kezelni kell, hogy a felület helyesen jelenítse meg a betöltést, adatokat, hibákat és befejezést.
StreamController — egy osztály a dart:async csomagból, amely létrehoz és kezel egy Stream-et. A StreamController lehetővé teszi adatok hozzáadását, hibák feldolgozását és a folyam lezárását, annak életciklusát irányítva.
A StreamController két típusban létezik: single-subscription (egy előfizető) és broadcast (több előfizető). A single-subscription vezérlő egyszerre csak egy hallgatót fogad el — az újbóli feliratkozás kivételt okoz. A broadcast vezérlő több StreamBuilder számára teszi lehetővé, hogy egyszerre hallgassák ugyanazt a folyamot, ami hasznos a BLoC és a megosztott alkalmazásállapot számára.
A StreamController<T>.broadcast() segítségével történő StreamController létrehozásakor az első feliratkozás előtt hozzáadott adatok nem játszódnak le az új előfizető számára. Ha a csatlakozáskor meg kell szerezni az utolsó értéket, használja a BehaviourSubject-et az rxdart csomagból, amely gyorsítótárazza az utolsó eseményt.
A vezérlővel végzett munka befejezése után meg kell hívni a controller.close()-t. A close elmulasztása erőforrás-szivárgáshoz vezet: a folyam nyitva marad, az előfizetők a memóriában lógnak, és a GC nem szabadítja fel a kapcsolódó objektumokat.
Következtetés: használja a StreamController-t explicit életciklus-kezeléssel. Single-subscription folyamokhoz — standard vezérlő, megosztott állapothoz — broadcast vezérlő vagy BehaviourSubject.
1. példa egy visszaszámláló időzítőt mutat be StreamController és StreamBuilder használatával.
import 'dart:async';
class TimerWidget extends StatefulWidget {
const TimerWidget({super.key});
final StreamController<int> controller = StreamController<int>();
void startTimer() {
int count = 0;
Timer.periodic(Duration(seconds: 1), (timer) {
controller.sink.add(count++);
if (count > 10) {
controller.close();
timer.cancel();
}
});
}
}
A példában egy vezérlő jön létre 0-tól 10-ig terjedő számok generálására 1 másodperces időközzel. A 10 elérése után meghívásra kerül a close, és a folyam befejeződik. A vezérlő stream-jére feliratkozott StreamBuilder minden új értéket megjelenít.
2. példa — a StreamBuilder használata Broadcast Stream-mel több forrásból származó adatok megjelenítésére.
final StreamController<String> broadcastController =
StreamController<String>.broadcast();
StreamBuilder<String>(
stream: broadcastController.stream,
initialData: 'Waiting for data...',
builder: (context, AsyncSnapshot<String> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(
child: CircularProgressIndicator(),
);
}
if (snapshot.hasError) {
return Text('Error: ${snapshot.error}');
}
return Text('Data: ${snapshot.data}');
},
)
A második példa az összes állapot kezelését mutatja: initialData a kezdeti megjelenítéshez, waiting a betöltés jelzőhöz, hasError a hibákhoz és data a sikeres eredményhez. Ez a minta a StreamBuilder-rel készült termelési kód szabványa.
Következtetés: használja az initialData-t az üres képernyő elkerülésére az első pillanatban, és mindig kezelje a hasError-t a hibák helyes megjelenítéséhez a felhasználó számára.
1. hiba: új Stream létrehozása a szülő minden újraépítésekor. Ha a Stream olyan kifejezésen keresztül kerül átadásra, amely minden építéskor új objektumot hoz létre, a StreamBuilder leiratkozik a régi folyamról és feliratkozik az újra, végtelen újraépítési ciklust okozva. Megoldás: használjon remembered változót vagy StatefulWidget-et rögzített Stream-mel.
2. hiba: a hibakezelés hiánya. A Stream controller.sink.addError segítségével hibákat bocsáthat ki, és ha a builder nem ellenőrzi a snapshot.hasError-t, a felhasználó üres képernyőt vagy végtelen betöltést lát. Megoldás: mindig ellenőrizze a hasError-t és jelenítsen meg érthető üzenetet.
3. hiba: memóriaszivárgás a le nem zárt StreamController miatt. Ha a vezérlő nincs lezárva a dispose-ban, a folyam továbbra is létezik, és a GC nem szabadítja fel a memóriát. Megoldás: hívja meg a controller.close()-t a dispose-ban, és figyelje a done eseményt a befejező műveletekhez.
4. hiba: a StreamBuilder használata lassú builder függvénnyel. Mivel a builder a folyam minden eseményénél meghívásra kerül, a benne lévő nehéz számítások képkocka-kieséshez vezetnek. Megoldás: helyezze át a számításokat egy külön izolátumba, vagy használja a Stream.map-et az adatok átalakításához.
Következtetés: a StreamBuilder egy hatékony, de igényes eszköz. Figyelje a Stream életciklusát, kezelje a hibákat, és kerülje a nehéz műveleteket a builder-ben.
Gyakran Ismételt Kérdések
FutureBuilder egyszeri aszinkron eredményre lett tervezve: feliratkozik egy Future-re, kap egy értéket és befejezi a munkát. A StreamBuilder feliratkozik egy Stream-re, amely idővel több értéket is kibocsáthat, és minden új eseménynél újraépíti a UI-t.
AsyncSnapshot — egy megváltoztathatatlan objektum, amely tartalmazza a jelenlegi feliratkozási állapotot (connectionState), az utolsó kapott értéket (data) és a hiba objektumot (error), ha a folyam kivételt bocsátott ki.
Hiba kezelése a snapshot.hasError és snapshot.error tulajdonságokon keresztül történik a builder függvényben. Ha a folyam a sink.addError metódussal hibát bocsát ki, az AsyncSnapshot error-t kap, és a builder-nek megfelelő üzenetet vagy tartalék UI-t kell megjelenítenie.
Igen, ha a Stream broadcast típusú (StreamController.broadcast segítségével létrehozva). A single-subscription Stream csak egy előfizetőt engedélyez. Egy folyam megosztásához több widget között használjon broadcast vezérlőt vagy az rxdart csomagot BehaviourSubject-tel.
Használja a buildWhen paramétert azon események szűrésére, amelyeknél a UI-t újra kell építeni. Alkalmazza továbbá a Stream.transformer vagy Stream.where függvényeket az adatok szűrésére, mielőtt azokat a StreamBuilder-nek átadná.
Összegzés
Kulcsrakész mobilalkalmazást fejlesztünk
Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.
Olvassa el is