StatefulWidget: mi ez, életciklus és működési elv

Szerző: IT Sectr Megjelenés: 2026-07-01 Olvasási idő: 9 perc

StatefulWidget — egy Flutter widget változtatható állapottal, amely lehetővé teszi a UI számára, hogy reagáljon a felhasználói műveletekre, aszinkron eseményekre és adatfolyamokra. A hivatalos Flutter dokumentáció szerint (Flutter.dev, 2026), a StatefulWidget az alkalmazás összes interaktív eleméhez használatos: beviteli mezők, animációk, jelölőnégyzetek, kapcsolók és hálózatból adatokat betöltő képernyők. A StatelessWidget-től eltérően létrehoz egy külön State objektumot, amely a teljes életciklus alatt megmarad, és újjáépíthető a widget újbóli létrehozása nélkül.

Főbb pontok

  • StatefulWidget — egy widget, amely működés közben megváltoztathatja állapotát, kiváltva a UI újjáépítését a setState segítségével
  • Életciklus — a StatefulWidget a createState, initState, didChangeDependencies, build, didUpdateWidget, dispose fázisokon megy keresztül
  • State objektum — egy külön objektum, amely tárolja az állapotot, és a widgettől függetlenül létezik annak teljes élete során
  • setState — az egyetlen legitim módja annak, hogy értesítse a Flutter-t a widget újjáépítésének szükségességéről adatváltozás után
  • Teljesítmény — a StatefulWidget túlzott használata növeli a memóriafogyasztást és a megjelenítési időt

Mi az a StatefulWidget?

StatefulWidget — egy Flutter osztály, amely megváltoztathatja állapotát a felhasználói műveletekre, rendszereseményekre vagy aszinkron műveletekre válaszul. A StatelessWidget-től eltérően a StatefulWidget nem közvetlenül jelenik meg — létrehoz egy State objektumot, amely a megjelenítésért felelős. A két osztályra (Widget és State) bontás lehetővé teszi a Flutter számára, hogy újjáépítse a UI-t a widget újbóli létrehozása nélkül, ami jelentős teljesítményelőnyt biztosít gyakori frissítések esetén.

A StatefulWidget architektúrája a «változtatható és változtathatatlan szétválasztása» mintát követi: maga a widget változtathatatlan marad (mint a StatelessWidget), míg az összes változtatható állapot egy külön State objektumban tárolódik. Ez lehetővé teszi a Flutter számára a widgetek újrafelhasználását típus és Key alapján történő összehasonlítással, miközben megtartja az aktuális állapotot az újjáépítések között.

A Google szerint (Flutter Architectural Overview, 2026) a StatefulWidget optimális azokhoz a forgatókönyvekhez, ahol az állapot többször változik a widget élettartama során: szövegmezők, animációk, időzítők, adatfolyamok, aszinkron betöltések. Egyszeri inicializáláshoz a StatelessWidget elegendő.

Mikor szükséges a StatefulWidget

StatefulWidget kötelező, ha a widgetnek reagálnia kell külső eseményekre: gombnyomás, HTTP-kérés befejezése, adatbázis-frissítés, WebSocket feliratkozás. Szükséges továbbá animációs widgetekhez, vezérlőkkel ellátott szövegmezőkhöz és fókuszt kezelő komponensekhez. Ha a widget csak adatokat jelenít meg és nem generál eseményeket — használjon StatelessWidget-et.

Belső felépítés

A StatefulWidget két osztályból áll: magából a StatefulWidget-ből (könnyű, változtathatatlan) és a State-ből (nehéz, változtatható). A keretrendszer a createState() metóduson keresztül hozza létre a State-t, amely egyszer hívódik meg a fába történő beágyazáskor. A State a widget tulajdonságon keresztül kap referenciát a widgetre, és az életciklus bármely pontján hozzáférhet annak mezőihez.

A StatefulWidget életciklusa

Az életciklus StatefulWidget hat fő szakaszból áll, amelyek mindegyike felülírható metódust biztosít specifikus feladatok végrehajtásához. Ezen szakaszok megértése kritikus fontosságú az erőforrásokkal való helyes munkához és a memóriaszivárgások elkerüléséhez.

createState

createState — az életciklus első metódusa, amely a StatefulWidget fába történő beágyazásakor hívódik meg. Vissza kell adnia a widgethez társított State új példányát. Ez a metódus pontosan egyszer hívódik meg az elem teljes élettartama alatt. Fontos, hogy ne végezzünk nehéz műveleteket itt — a createState-nek a lehető legkönnyebbnek kell lennie.

initState

initState — közvetlenül a State létrehozása után hívódik meg, az első UI-építés előtt. Itt történik: vezérlők inicializálása (TextEditingController, AnimationController), adatfolyamokra való feliratkozás (StreamSubscription), időzítők beállítása és a mezők kezdeti inicializálása. A Flutter dokumentáció szerint (Flutter.dev, 2026) az initState-ben nem hívható meg a BuildContext.of() — a fa még nincs teljesen felcsatolva.

didChangeDependencies

didChangeDependencies — az initState után és minden alkalommal meghívódik, amikor az InheritedWidget függőségei megváltoznak. Ez a megfelelő hely a MediaQuery.of(context) meghívásához vagy a Theme-re való feliratkozáshoz — olyan értékek, amelyek az alkalmazás futása közben megváltozhatnak. Ha a widget InheritedWidget-ot használ, az inicializálási logikának itt kell lennie, nem az initState-ben.

build és didUpdateWidget

build — a fő metódus, amely visszaadja a widget fát. Az initState után, a didChangeDependencies után és minden setState után hívódik meg. didUpdateWidget akkor hívódik meg, amikor a szülő újjáépíti és új paraméterekkel adja át a StatefulWidget-et. Itt összehasonlíthatja a widget régi és új mezőit, és szükség esetén frissítheti az állapotot.

dispose

dispose — az életciklus utolsó szakasza. Itt szabadulnak fel az összes erőforrás: leiratkozás a folyamokról, vezérlők törlése, időzítők lemondása. A dispose elmulasztása memóriaszivárgáshoz vezet. A dispose után a State halottnak tekintendő — a benne lévő setState hívás kivételt dob.

Hogyan működik a StatefulWidget?

A StatefulWidget működési mechanizmusa három entitás összehangolt munkáján alapul: Widget (könnyű leírás), Element (köztes réteg) és State (adat tároló). Amikor a Flutter StatefulWidget-et talál a leírásban, létrehoz egy StatefulElement-et, amely meghívja a createState-t és tárolja a referenciát a State objektumra. A szülő újjáépítésekor a Flutter összehasonlítja az új widget-et az aktuális Element-tel — ha a típus és a Key megegyezik, az Element frissül, a State pedig változatlan marad.

Az állapot csak a setState meghívásával változik, amely értesíti a keretrendszert az újjáépítés szükségességéről. Fontos megérteni: a setState nem változtatja meg automatikusan az állapotot — csak «piszkosnak» jelöli a widget-et. A fejlesztő maga frissíti a State mezőit a setState-nek átadott callback-ben. A callback befejezése után a Flutter meghívja a build-t és frissíti a UI-t.

A Dart/Flutter csapat szerint (Dart Language Specification, 2026) ez a szétválasztás garantálja, hogy az összes állapotváltozás szinkron módon történjen a build meghívása előtt, kizárva azt a helyzetet, amikor a UI részlegesen frissített adatokat jelenít meg. Ez a felület konzisztenciájának kulcsmechanizmusa a Flutter-ben.

Kódpéldák Dart-ban

Vegyünk egy egyszerű StatefulWidget-et — egy gomb kattintásszámlálóját. Ez bemutatja az alapmintát: a State létrehozása, a mező inicializálása az initState-ben, változtatás a setState segítségével:

dart
class CounterScreen extends StatefulWidget {
  const CounterScreen({super.key});

  @override
  State<CounterScreen> createState() => _CounterScreenState();
}

class _CounterScreenState extends State<CounterScreen> {
  int _count = 0;

  void _increment() {
    setState(() {
      _count++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text('Szám: $_count'),
        ElevatedButton(
          onPressed: _increment,
          child: const Text('Növelés'),
        ),
      ],
    );
  }
}

Példa aszinkron adatbetöltéssel és életciklus-kezeléssel. A StatefulWidget adatokat tölt be a hálózatból és megjeleníti a betöltési állapotot:

dart
class UserProfilePage extends StatefulWidget {
  final String userId;
  const UserProfilePage({super.key, required this.userId});

  @override
  State<UserProfilePage> createState() => _UserProfilePageState();
}

class _UserProfilePageState extends State<UserProfilePage> {
  UserModel? _user;
  bool _isLoading = true;

  @override
  void initState() {
    super.initState();
    _loadUser();
  }

  Future<void> _loadUser() async {
    final user = await UserService.fetchUser(widget.userId);
    setState(() {
      _user = user;
      _isLoading = false;
    });
  }

  @override
  Widget build(BuildContext context) {
    if (_isLoading) return const CircularProgressIndicator();
    return Text('Helló, ${_user!.name}');
  }
}

A második példában fontos megjegyezni: az initState elindít egy aszinkron műveletet, de maga a metódus nem aszinkron. Az aszinkronitás az async/await segítségével valósul meg a külön _loadUser metóduson belül, amely a kérés befejezése után a setState segítségével frissíti az állapotot. Ez a megközelítés garantálja, hogy a widget helyesen jelenítse meg a betöltés jelzőt az adatok megérkezése előtt.

StatefulWidget vs StatelessWidget

A StatefulWidget és a StatelessWidget közötti választás nem csupán az állapot meglétének kérdése. A StatefulWidget teljes életciklust biztosít az initState, didChangeDependencies, didUpdateWidget és dispose metódusokkal, ami szükséges a vezérlőkkel, animációkkal és folyamokkal való munkához. A StatelessWidget viszont nem rendelkezik ezekkel a metódusokkal, és mindig könnyebb a keretrendszer számára.

A Flutter csapat ajánlása (Flutter docs, 2026) — minimalizálja a StatefulWidget-ek számát az alkalmazásban az állapot fában történő felemelésével (State Hoisting) vagy állapotkezelő megoldások használatával (Riverpod, Bloc, Provider). Minden StatefulWidget létrehoz egy State objektumot, amely az elem eltávolításáig él — minél több ilyen widget van, annál nagyobb a memóriaterhelés.

SzempontStatefulWidgetStatelessWidget
ÁllapotVáltoztathatóVáltoztathatatlan
Életciklus6 szakaszCsak build
State objektumKülön létrehozvaNem szükséges
setStateElérhetőNem elérhető
FeliratkozásokinitState/disposeNem támogatott
const konstruktorKorlátozottTeljesen támogatott
MemóriafogyasztásMagasabbAlacsonyabb

Teljesítmény és optimalizálás

StatefulWidget több erőforrást igényel, mint a StatelessWidget a State objektum létrehozásának és karbantartásának szükségessége miatt. Azonban a StatefulWidget helyes használata nem vezet teljesítményproblémákhoz, ha néhány szabályt betartanak. Először is, kerülje a StatefulWidget mély egymásba ágyazását — minden szint többletterhelést ad a fa bejárásához. Másodszor, ossza fel az összetett StatefulWidget-et több egyszerű widgetre, amelyek mindegyike az állapot egy-egy részéért felelős.

A Flutter Performance kutatás szerint (Flutter.dev, 2026. február) az FPS csökkenésének leggyakoribb oka a setState meghívása a szülő widget-ben, amely az összes leszármazottat újjáépíti, beleértve azokat a StatelessWidget-eket is, amelyek nem változtatták meg megjelenítésüket. A megoldás — helyezze át a UI változtatható részét egy külön StatefulWidget-be, hogy a setState csak a minimálisan szükséges widget-eket építse újjá.

A const használata a State-en belül egy másik fontos technika. Ha a gyermek widget-ek const-ként vannak deklarálva, a Flutter nem építi újjá őket a setState szülőben történő meghívásakor. Ez csökkenti a keretrendszer terhelését és lerövidíti a képkocka megjelenítési idejét.

Kerülje a gyakori setState hívásokat

Minden setState hívás a widget teljes újjáépítését indítja el. Ha az állapot nagy gyakorisággal változik (például animáció vagy adatfolyam), fontolja meg az AnimatedBuilder, ValueListenableBuilder vagy StreamBuilder használatát a kézi setState hívás helyett. Ezek a widget-ek optimalizálják az újjáépítést, csak a ténylegesen megváltozott UI részt frissítve.

Gyakori hibák

Az első gyakori hiba a StatefulWidget-tel — a setState meghívása a dispose után. Amikor a widget eltávolításra kerül a fából, a State halottnak tekintendő, és minden setState hívás a «setState called after dispose» kivételt dobja. Leggyakrabban ez akkor történik, amikor egy aszinkron művelet a widget eltávolítása után fejeződik be. A megoldás — ellenőrizze a mounted jelzőt a setState meghívása előtt, vagy mondja le az aszinkron műveleteket a dispose-ban.

A második hiba — nehéz számítások végrehajtása a build metódusban. Mivel a build minden setState és minden szülő újjáépítésekor meghívódik, minden számításnak a lehető legkönnyebbnek kell lennie. Ha erőforrás-igényes műveletet kell végrehajtani — helyezze át egy külön Isolate-ba, vagy gyorsítótárazza az eredményt egy State mezőben.

A harmadik hiba — a super.initState() és a super.dispose() elmulasztása. Ezen metódusok felülírásakor a fejlesztő köteles meghívni a szülő implementációt. Ha ez nem történik meg, a keretrendszer nem tudja megfelelően kezelni az Element állapotát, ami nehezen megtalálható hibákhoz vezet.

Javaslatok a hibák elkerülésére

  • Mindig ellenőrizze a mounted jelzőt a setState előtt aszinkron callback-ekben
  • Ne felejtse el meghívni a super.initState() és super.dispose() metódusokat
  • Ne végezzen HTTP-kéréseket közvetlenül a build-ben — használja az initState-t
  • Mondjon le minden feliratkozást a dispose-ban
  • Használjon minimális számú StatefulWidget-et a projektben

Gyakran Ismételt Kérdések

Miben különbözik a StatefulWidget a StatelessWidget-től?

StatefulWidget megváltoztathatja állapotát a setState segítségével, életciklussal rendelkezik (initState, dispose) és létrehoz egy külön State objektumot. A StatelessWidget nem tudja megváltoztatni az állapotát és nem rendelkezik életciklus metódusokkal — csak a kapott adatokat jeleníti meg.

Hányszor hívódik meg a createState?

createState pontosan egyszer hívódik meg minden StatefulElement példányhoz. Még ha a szülő többször újjá is épül, amíg a widget típusa és Key-je nem változik, a createState nem hívódik meg — a meglévő State objektum kerül felhasználásra.

Mi történik, ha nem hívják meg a dispose-t?

Az erőforrások nem szabadulnak fel: a vezérlők tovább működnek a háttérben, a folyamfeliratkozások aktívak maradnak, az időzítők nem mondódnak le. Ez memóriaszivárgáshoz vezet, és a dispose utáni setState hívást okozhat, ami kivételt dob.

Lehet-e a StatefulWidget const?

Igen, a konstruktor StatefulWidget lehet const. Ez azonban nem nyújtja ugyanazt az előnyt, mint a StatelessWidget esetében — a State objektum akkor is létrejön az első beágyazáskor. A const csak magára a widget-re (a könnyű burkolóra) hat, nem a State-re.

Mire való a didUpdateWidget metódus?

didUpdateWidget akkor hívódik meg, amikor a szülő új paraméterekkel adja át a StatefulWidget-et. Ez szükséges az állapot és az új adatok szinkronizálásához — például ha a userId megváltozott a paraméterekben, be kell tölteni az új felhasználó profilját.

Összefoglalás

  • StatefulWidget — változtatható állapotú widget, amely külön State objektumot használ az adatok tárolására és az életciklus kezelésére
  • Életciklus createState, initState, didChangeDependencies, build, didUpdateWidget és dispose szakaszokból áll, mindegyiknek megvan a maga célja
  • setState — az egyetlen legitim módja a keretrendszer értesítésének az állapotváltozásról, amely után a build automatikusan meghívódik
  • mounted — jelző, amelyet a setState előtt ellenőrizni kell aszinkron műveletekben a dispose utáni kivétel elkerülése érdekében
  • Teljesítmény — a StatefulWidget több erőforrást igényel, mint a StatelessWidget; számuk csökkentése az állapot külső rétegekbe helyezésével javasolt
  • Const gyermek widget-ek a State-en belül lehetővé teszik az újjáépítés mértékének csökkentését a setState hívásakor, javítva a teljesítményt
  • Helyes választás — használjon StatefulWidget-et csak akkor, ha a widget-nek változtatható adatokat vagy aszinkron műveleteket kell kezelnie

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.

Projekt megbeszélése

Olvassa el is