State — a Flutter központi adatkezelő objektuma, amely a StatefulWidgethez kapcsolódik és felelős a változtatható információk tárolásáért és a felület felépítéséért. A Flutter hivatalos dokumentációja szerint (Flutter.dev, 2026) a State a widget teljes életciklusa alatt létezik és túbbírja annak újraépítéseit, biztosítva az adatok konzisztenciáját az UI frissítések között. Magától a widgettől eltérően a State megváltoztathatja a mezőit és a setState meghívásával újraépítést kezdeményezhet.
FŐ PONTOK
State — egy objektum a Flutter architektúrában, amely tárolja a StatefulWidget változtatható adatait és meghatározza, hogy ezek az adatok hogyan jelenjenek meg a felületen. Minden StatefulWidget a fába való beágyazáskor pontosan egy State objektumot hoz létre a createState metódussal. A State függetlenül létezik a widgettől: ha a szülő újraépíti a StatefulWidgetet új paraméterekkel, a State ugyanaz marad és a frissített widgetet a widget tulajdonságon keresztül kapja meg.
A Flutter Architectural Overview (Google, 2026) szerint a Widget és a State szétválasztása egy tudatos architektúrai döntés, amely lehetővé teszi a keretrendszer számára a faelemek újrafelhasználását. A widget (könnyű leírás) többször létrehozható és megsemmisíthető, de a State (nehéz objektum adatokkal) a memóriában marad, amíg az elem a fában van. Ez megakadályozza az adatvesztést a szülő widgetek gyakori újraépítésekor.
A State a StatefulWidget interfészt generikuson keresztül valósítja meg: class _MyState extends State<MyWidget>. A generikus a State-t egy konkrét StatefulWidget típushoz köti, típusbiztos hozzáférést biztosítva a mezőihez a widget tulajdonságon keresztül.
A State objektum a StatefulElement-ben tárolódik — a Widget és a RenderObject közötti közbenső rétegben. A StatefulElement a createState-en keresztül hozza létre a State-t, tárolja a rá való hivatkozást és átadja a State-t tulajdonosként. Az Element csak akkor semmisül meg, amikor a widget eltávolításra kerül a fából — addig a State a memóriában él.
A State életciklusa determinisztikus és szigorú hívási sorrendből áll. Ennek a sorrendnek a megértése az erőforrásokkal való helyes munkavégzes és a memóriaszivárgás megelőzésének alapja.
initState elsőként hívódik meg a State létrehozásakor. Ebben a metódusban inicializálódnak a vezérlők, adatfolyam-előfizetések, időzítők és a mezők kezdeti értékei. A super.initState() meghívása az első sorban kötelező. Az initState fázisban a widgetfá még nincs teljesen felszerelve, ezért az olyan metódusok, mint a MediaQuery.of(context), helytelenül működhetnek.
didChangeDependencies az initState után és az InheritedWidget függőségek minden változásakor hívódik meg. Itt, nem az initState-ben kell meghívni a MediaQuery.of(context) vagy Theme.of(context) metódusokat, mert ekkor a fá már fel van szerelve. Ez a metódus akkor is meghívódik, ha a widget egy másik kontextusba kerül, ahol az InheritedWidget eltérő értékeket biztosít.
build — a State fő metódusa, amely visszaadja a widgetfát. Az initState után, a didChangeDependencies után és minden setState után hívódik meg. A build metódusnak nem lehetnek mellékhatásai — csak a State mezőinek aktuális értékei alapján írja le a felületet.
didUpdateWidget akkor hívódik meg, amikor a szülő újraépíti a StatefulWidgetet új paraméterekkel. A State hozzáfér a régi widgethez az oldWidget-en keresztül, és összehasonlíthatja azt az újjal. Ha a paraméterek megváltoztak, frissíthető az állapot, betölthetők új adatok vagy újraindítható az animáció.
dispose — a záró metódus, amelyben az összes erőforrás felszabadul: vezérlők, előfizetések, időzítők. A dispose után a State halottként van megjelölve: a mounted false-értéket ad vissza, a setState meghívása kivételt dob. A super.dispose() meghívása a metódus utolsó sorában kötelező.
| Metódus | Mikor hívódik | Kötelező super |
|---|---|---|
| initState | A State létrehozásakor | Igen, az első sorban |
| didChangeDependencies | Az initState után és InheritedWidget változásakor | Igen |
| build | Az initState, didChangeDependencies, setState után | Nem |
| didUpdateWidget | Új widget érkezésekor a szülőtől | Igen |
| setState | A fejlesztő hívására | Nem |
| dispose | A fából való eltávolításkor | Igen, az utolsó sorban |
A State működési mechanizmusa három kulcsfontosságú elven alapul: az Element-hez való kapcsolódás, a setState-en keresztüli reaktivitás és a szülőhöz való hozzáférés a widget tulajdonságon keresztül. Amikor a Flutter építi az elemfát és StatefulElement-re bukkan, meghívja a kapcsolódó widget createState metódusát. A létrehozott State az elemben tárolódik és addig létezik, amíg az elmet nem törlődik.
A setState meghívásakor a State „piszkos“nak” (dirty) jelöli meg magát és újraépítést ütemez a következő kockára. Fontos: a setState nem hívja meg azonnal a build-et — csak regisztrálja az újraépítés szükségességét. A Flutter összegyűjti az összes piszkos elemet az aktuális kockában és kötegenként építi őket újra, ami optimalizálja a teljesítményt. A build hívás után a State visszatér a „tiszta” (clean) állapotba.
A widget tulajdonság lehetővé teszi a State számára, hogy olvassa a StatefulWidget konstruktorának átadott paramétereket. Mivel a StatefulWidget megváltoztathatatlan (mint a StatelessWidget), a mezői nem változnak — a paraméterek változásakor a szülő új widgetet hoz létre, és a State azt a didUpdateWidget-en keresztül kapja meg. Ez garantálja, hogy a State mindig a szülő aktuális adataival dolgozik.
Alap példa State-re egy időzítő által módosított mezővel. Bemutatja az initState, setState és dispose metódusokat:
class _TimerWidgetState extends State<TimerWidget> {
int _seconds = 0;
Timer? _timer;
@override
void initState() {
super.initState();
_timer = Timer.periodic(
const Duration(seconds: 1),
(_) => setState(() => _seconds++),
);
}
@override
void dispose() {
_timer?.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Text('$_seconds másodperc telt el');
}
}
Példa a widget tulajdonság használatára a szülő paramétereinek eléréséhez és azok változásaira való reagáláshoz a didUpdateWidget-en keresztül:
class _GreetingState extends State<GreetingWidget> {
String _displayName = '';
@override
void initState() {
super.initState();
_displayName = _formatName(widget.name);
}
@override
void didUpdateWidget(GreetingWidget oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.name != oldWidget.name) {
setState(() {
_displayName = _formatName(widget.name);
});
}
}
String _formatName(String name) => name.trim().isEmpty ? 'Guest' : name;
@override
Widget build(BuildContext context) {
return Text('Üdvözlöm, $_displayName!');
}
}
A második példában a State nyomon követi a name bemeneti paraméter változását és csak tényleges változáskor formázza újra a megjelenítést. A widget.name != oldWidget.name ellenőrzés nélkül a metódus a szülő minden újraépítésekor meghívódna, még akkor is, ha a név nem változott — ez felesleges munka a keretrendszer számára.
A State és a StatefulWidget két különböző osztály a Flutter architektúrában, különböző szerepkörrel. A StatefulWidget egy könnyű, megváltoztathatatlan burkoló, amely leírja a widget konfigurációját és létrehozza a State-t. A State egy nehéz objektum, amely tárolja a változtatható adatokat, kezeli az előfizetéseket és építi az UI-t. Ez a szétválasztás lehetővé teszi a Flutter számára, hogy állapotvesztés nélkül semmisítse meg és hozza létre a widgeteket.
A StatefulWidget összes mezőjének finalnek kell lennie és a konstruktorban kell beállítani — nem változnak a létrehozás után. A State ezzel szemben bármikor megváltoztathatja a mezőit, de minden változást meg kell előznie a setState meghívásának, hogy a Flutter tudomást szerezzen az újraépítés szükségességéről. Ez a fő különbség: a StatefulWidget az „hogy mit mutasson”, a State pedig az „hogyan mutasson és milyen adatokat használjon”.
A Flutter forráskód-elemzés (Flutter SDK, 2026) szerint a StatefulWidget csak egy kötelező mezőt tartalmaz — a createState-et, míg a State hozzáfér a BuildContext-hez, előfizethet adatfolyamokra, kezelhet animációkat és vezérlőket. Ajánlott a StatefulWidgetet a lehető legegyszerűbbé tenni, áthelyezve az összes logikát a State-be.
A Widget és a State szétválasztása egy architektúrai döntés, amely biztosítja a konfiguráció megváltoztathatatlanságát. Ha a StatefulWidget maga tárolná az állapotot, a szülő minden újraépítésekor az állapot elveszne. Az állapot külön objektumba helyezésével a Flutter garantálja, hogy az adatok túbbírják az újraépítéseket, a widgetek pedig könnyűek és összehasonlíthatók maradnak.
A State objektum el van szigetelve — nincs közvetlen hozzáférése más widgetek State-jéhez. A widgetek közötti adatcseréhez InheritedWidget vagy külső állapotkezelő eszközök használatosak: Provider, Riverpod, Bloc, Redux. Minden megközelítés másképp oldja meg a feladatot: az InheritedWidget a widgetfán keresztül dolgozik, a Provider — DI-konténeren keresztül, a Bloc — eseményfolyamokon keresztül.
Az eszköz választása a projekt méretétől függ. Kis alkalmazáshoz elegendő az InheritedWidget és a helyi State. Közepes és nagy projekthez a Riverpod vagy a Bloc ajánlott — ezek tesztelhetőséget, kiszámíthatóságot és a logika UI-tól való elkülönítését biztosítják. A State ekkor csak a widget helyi adataihoz használatos (fókusz, görgetés, animáció).
A Flutter Community Survey 2025 (Flutter Foundation, 2025. december) szerint a Riverpod a legnépszerűbb állapotkezelő megoldás új projektekben (38%), ezt követi a Bloc (31%) és a Provider (22%). Mindhárom eszköz kompatibilis a State-tel és nem igényli a szabványos életciklus elhagyását.
Első hiba — elfelejteni ellenőrizni a mounted-et a setState előtt egy aszinkron visszahívásban. Amikor a widget eltávolításra került a fából (pl. a felhasználó elhagyta a képernyőt), de az aszinkron művelet (HTTP kérés) még fut, a befejezése után a State már halott. A setState meghívása egy halott State-ben kivételt dob. Az if (mounted) setState(...) ellenőrzés megoldja a problémát.
Második hiba — az InheritedWidget függőségek inicializálása az initState-ben a didChangeDependencies helyett. Az initState-ben a kontextus még nincs felszerelve, ezért a MediaQuery.of(context) kivételt dob. Az InheritedWidget-től származó összes függőséget a didChangeDependencies-ben vagy a build-ben kell konfigurálni.
Harmadik hiba — mezők mutálása a setState meghívása nélkül. Ha a fejlesztő setState nélkül módosít egy State mezőt, a Flutter nem értesül a változásról és az UI nem frissül. Például: a _list.add(item) az ezt követő setState((){}) nélkül megváltoztatja a listát, de a képernyő változatlan marad.
Biztonsági minta aszinkron műveletekhez a State-ben:
Future<void> _fetchData() async {
final data = await ApiService.fetch();
if (mounted) {
setState(() => _data = data);
}
}
A mounted ellenőrzés garantálja, hogy a setState csak élő State esetén hívódik meg, megakadályozva a „setState called after dispose” kivételt.
Gyakran Ismételt Kérdések
A StatefulWidget a widget megváltoztathatatlan konfigurációja, míg a State egy változtatható objektum, amely tárolja az adatokat és kezeli az életciklust. A widget újra létrehozható, a State — nem. A StatefulWidget a createState-en keresztül hozza létre a State-t.
Pontosan egy. A createState metódus egyszer hívódik meg a StatefulWidget első fába ágyazásakor. Még ha a szülő többször újraépül, a State objektum ugyanaz marad, amíg a widget típusa vagy Key-je meg nem változik.
A mounted egy logikai jelző, amely megmutatja, hogy a State a widgetfában van-e. A dispose meghívása után a mounted false lesz. Aszinkron visszahívásokban a setState előtti ellenőrzésre használják a kivétel elkerülése érdekében.
Nem. A State mindig egy adott StatefulWidgethez van kötve generikuson keresztül: State<T extends StatefulWidget>. A State közvetlen létrehozása, widgethez való kapcsolódás nélkül, architektúrailag lehetetlen.
Kivétel dobódik: „setState called after dispose”. A dispose meghívása után a State halottnak tekintendő és az UI setState-en keresztüli újraépítésére tett kísérletek tilosak. Megoldás — ellenőrizze a mounted-et minden setState előtt.
Összefoglaló
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