setState() — lényeg, működési mechanizmus és alkalmazás

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

setState() — a State osztály kulcsmetódusa a Flutter-ben, amely értesíti a keretrendszert az adatok változásáról és elindítja a felület újraépítését. A hivatalos Flutter dokumentáció szerint (Flutter.dev, 2026) a setState a reaktivitás fő mechanizmusa a StatefulWidget-ben: hívása nélkül az UI nem tud a State mezők változásairól, és az előző állapotban marad. A metódus egy VoidCallback-et fogad, amelyen belül a fejlesztő módosítja a változó mezőket, majd a Flutter automatikusan meghívja a build-et a widget újraépítéséhez.

Főbb pontok

  • setState() — State metódus, amely piszkosnak (dirty) jelöli a widget-et és az UI újraépítését tervezi a következő képkockában
  • Callback — a setState VoidCallback-et fogad, amelyen belül kell lennie az interfészt befolyásoló State mezők összes változásának
  • Aszinkronitás — a setTimeout vagy Future a setState-en belül nem garantálja a szinkronitást; az await utáni mutációknak egy másik setState-en belül kell lenniük
  • Teljesítmény — minden setState hívás újraépíti az egész widget-et; minimalizáláshoz használjon const-ot a gyermek widget-ekhez
  • mounted — aszinkron callback-ekben a setState hívása előtt mindig ellenőrizze a mounted-et, különben — kivétel

Mi az a setState()?

setState() — a State osztály beépített metódusa a Flutter-ben, amely a keretrendszer értesítésére szolgál arról, hogy a widget belső állapota megváltozott és az UI újraépítése szükséges. A setState hívása nélkül a Flutter nem tud a változásokról — még ha a State mezők módosultak is, a felület változatlan marad a szülő általi következő kényszerített újraépítésig.

A metódus aláírása: void setState(VoidCallback fn). A callback szinkron módon hajtódik végre a setState-en belül, és csak a befejezése után kerül a State dirty-nek jelölésre. Ez garantálja, hogy minden változás atomi módon kerül alkalmazásra az újraépítés előtt. A Dart Language Specification (Dart Team, 2026) szerint a setState atomicitása megakadályozza a versenyhelyzetet, ahol a build részlegesen frissített állapotot láthatna.

A setState nem fogad argumentumokat, nem ad vissza értéket és nem írható felül. Ez a State osztály végleges (sealed) metódusa. A fejlesztő nem változtathatja meg a viselkedését — csak rendeltetésszerűen használhatja. A setState State-en kívüli (pl. másik osztályból történő) meghívása lehetetlen, mivel a metódus a State osztályban van deklarálva.

A setState nem változtatja meg az állapotot — Ön változtatja meg

Egy gyakori tévhit — azt gondolni, hogy a setState maga változtatja meg az állapotot. Ez nem igaz. A setState csak meghívja az átadott callback-et (amelyben a fejlesztő módosítja a mezőket), majd jelzi a keretrendszernek a build szükségességét. A callback kötelező — null vagy üres callback átadása hibát okoz.

Hogyan működik a setState()?

A setState() működési mechanizmusa négy szakaszra osztható. Első — a metódus meghívása callback-kel. Második — a callback szinkron végrehajtása, melyen belül a State mezők módosulnak. Harmadik — a State dirty-nek jelölése a speciális _dirty mezőben. Negyedik — az aktuális microtask végén a Flutter végigjárja az összes dirty elemet és meghívja azok build-jét a fában való megjelenés sorrendjében.

Fontos részlet: a setState nem hívja meg azonnal a build-et. A Flutter kötegelt frissítési stratégiát használ: az összes dirty elem összegyűjtésre kerül és egy képkockában épül újra. Ez azt jelenti, hogy ha a setState többször meghívásra kerül ugyanazon szinkron blokkon belül, a build csak egyszer hajtódik végre — az összes változás befejezése után. Ez az optimalizálás megakadályozza a többszörös újraépítést egy képkockán belül.

A Flutter Engine Team (Google, 2025) szerint a dirty-zászlók mechanizmusa a BuildOwner._dirtyElements bejárásán alapul. Minden dirty StatefulElement hozzáadásra kerül a listához és a képkocka frissítési szakaszában feldolgozásra kerül. Ha a widget a feldolgozás előtt eltávolításra került a fából, automatikusan kizárásra kerül a dirty elemek listájából.

A setState garanciái

  • A callback szinkron módon hajtódik végre a dirty jelölés előtt
  • A build legfeljebb egyszer kerül meghívásra képkockánként (még többszörös setState esetén is)
  • Az UI frissítése a következő képkockában történik (általában ~16ms 60 FPS-nél)
  • A dispose után a hívás tilos — kivétel dobódik
  • A build alatt a setState hívása tilos — végtelen ciklus

Kódpéldák Dart-ban

A setState() alap példája számláló növeléssel. A helyes használatot mutatja: mező módosítása a callback-en belül:

dart
class _CounterState extends State<CounterWidget> {
  int _count = 0;

  void _increment() {
    setState(() {
      _count++; // mező mutációja a callback-en belül
    });
  }

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: _increment,
      child: Text('$_count'),
    );
  }
}

Példa szövegmezővel és vezérlővel — setState() a jelszó láthatóságának kezelésére:

dart
class _PasswordFieldState extends State<PasswordField> {
  bool _obscured = true;
  final _controller = TextEditingController();

  void _toggleVisibility() {
    setState(() {
      _obscured = !_obscured;
    });
  }

  @override
  Widget build(BuildContext context) {
    return TextField(
      controller: _controller,
      obscureText: _obscured,
      decoration: InputDecoration(
        suffixIcon: IconButton(
          icon: Icon(_obscured ? Icons.visibility : Icons.visibility_off),
          onPressed: _toggleVisibility,
        ),
      ),
    );
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
}

Ebben a példában a setState() csak a _obscured logikai mezőt változtatja meg, ami a TextField újraépítését okozza új ikonnal és megjelenítési móddal. A szövegvezérlő nem jön létre újra — egyszer kerül inicializálásra az initState-ben és felszabadításra a dispose-ban.

Több mutáció egy setState-ben

Ha több mezőt kell módosítani, az összes változás egy setState-en belül történik. Ez garantálja, hogy a build konzisztens állapotot lát:

dart
setState(() {
  _isLoading = false;
  _items = newItems;
  _error = null;
});

Három mező módosul egy callback-ben — a build egyszer hajtódik végre és egyszerre látja az összes változást. Ha minden hívás külön setState lenne, a build akkor is egyszer hajtódna végre a dirty elemek kötegelt feldolgozásának köszönhetően.

Aszinkronitás és setState

A setState() egyik legfontosabb árnyalata — a viselkedése aszinkron műveletekkel. A setState callback szinkron módon hajtódik végre, de ha azon belül await kerül meghívásra, az await utáni kód a setState befejezése után hajtódik végre. Ez azt jelenti, hogy az await utáni mezőváltozások nem kerülnek rögzítésre az aktuális setState által.

Helyes megközelítés: az aszinkron művelet a setState-en kívül hajtódik végre, és a setState a befejezése után kerül meghívásra. Az eredmény fogadása és a setState hívása közötti összes kód szinkron kontextusban hajtódik végre az await után:

dart
// HELYES: await a setState-en kívül
Future<void> _loadData() async {
  final result = await ApiService.fetchData();
  setState(() {
    _data = result;
    _isLoading = false;
  });
}

// ROSSZ: await a setState-en belül — nincs frissítési garancia
void _loadDataWrong() {
  setState(() async {
    _data = await ApiService.fetchData(); // a setState visszatér az await befejezése előtt
    _isLoading = false; // ezt a kódot nem rögzíti a setState
  });
}

A Flutter dokumentáció szerint (Dart async patterns, 2026) az async-callback setState-nek való átadása antipattern, mivel a setState VoidCallback-et (szinkron függvényt) vár, míg az async függvény egy Future-t ad vissza, amely figyelmen kívül marad. Az első await utáni változások egy ilyen callback-ben nem kerülnek helyesen feldolgozásra a keretrendszer által.

mounted ellenőrzés aszinkron forgatókönyvekben

Aszinkron művelet után a setState() hívása előtt mindig ellenőrizze a mounted-et:

dart
if (mounted) {
  setState(() => _data = data);
}

Ha a widget az aszinkron művelet végrehajtása során eltávolításra került a fából, a mounted false lesz és a setState nem kerül meghívásra. Ez megakadályozza a kivételt és az erőforrás-szivárgást.

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

setState() — kényelmes, de potenciálisan költséges mechanizmus, ha meggondolatlanul használják. Minden setState hívás újraépíti az egész widget-et és annak összes leszármazottját (ha nem const). Mély fákban vagy gyakori hívások esetén ez FPS-csökkenéshez vezethet.

Fő optimalizálási stratégiák: minimalizálni az újraépítési területet (a változó UI részek külön StatefulWidget-ekbe helyezése), const használata a változatlan leszármazottakhoz és a setState hívásának kerülése szülő widget-ekben, ha csak egy kis UX részlet változott. Ha az állapot nagy gyakorisággal frissül (animáció, adatfolyam), fontolja meg az AnimatedBuilder vagy ValueListenableBuilder használatát.

A Flutter Performance Best Practices (Flutter.dev, 2026. február) szerint a valós alkalmazások profilozása azt mutatja, hogy az összes setState hívás akár 40%-a helyettesíthető const gyermek widget-ekkel vagy reaktív builderekkel (StreamBuilder, FutureBuilder). Ez 15–25%-kal csökkenti az átlagos képkocka-építési időt.

Mikor felesleges a setState

ForgatókönyvAlternatívaElőny
AnimációAnimatedBuilderCsak az animált widget-et építi újra
AdatfolyamStreamBuilderReagál a folyam minden elemére
Jövőbeli eredményFutureBuilderKezeli a betöltési/hiba állapotokat
Helyi értékValueListenableBuilderReagál egy érték változására

A setState alternatívái

A setState() sokoldalúsága ellenére nagy projektekben főként helyi állapothoz használják. Globális vagy megosztott állapothoz speciális megoldásokat használnak, amelyek mindegyike helyettesíti vagy becsomagolja a setState-et.

A Provider a ChangeNotifier + notifyListeners-t használja a setState analógjaként, de több widget feliratkozási lehetőségével. A Bloc a Streams-t használja — az állapot események StreamController-hez adásával változik. A Riverpod kombinálja a megközelítéseket, helyi (StateProvider) és aszinkron (AsyncNotifier) kezelést kínálva a StatefulWidget-hez való kötődés nélkül. Mindhárom megközelítés kiküszöböli a setState manuális hívásának szükségességét — az UI frissítése automatikusan történik az adatok változásakor.

A Flutter Community Survey 2025 (Flutter Foundation, 2025. december) szerint a fejlesztők 74%-a használ legalább egy állapotkezelő eszközt a setState mellett. Ugyanakkor 92% továbbra is használ setState-et a szövegmező, jelölőnégyzet vagy egyszerű számláló helyi adataihoz — ez tekinthető bevált gyakorlatnak (best practice).

Mikor tartsuk meg a setState-et

  • Az állapotot csak egy widget használja
  • Egyszerű logikai vagy numerikus érték (fókusz, láthatóság, számláló)
  • Prototípuskészítés és gyors kísérletezés
  • A vezérlők (TextEditingController, PageController) úgyis StatefulWidget-et igényelnek

Tipikus hibák

Az első és legveszélyesebb hiba — a setState hívása dispose után. Az aszinkron művelet az initState-ben indult, a felhasználó elhagyta a képernyőt, a widget eltávolításra került és az aszinkron művelet callback-je meghívja a setState-et — az alkalmazás összeomlik egy kivétellel. Megoldás — mindig ellenőrizze a mounted-et hívás előtt.

Második hiba — a setState hívása a build-en belül. Ez végtelen ciklushoz vezet: build → setState → dirty → build → setState → ... A Flutter nem blokkolja az ilyen hívást (StackOverflowError-t kap). A setState csak eseményre válaszul hívható (gombnyomás, Future befejeződése, adatok fogadása folyamból).

Harmadik hiba — a State mezők módosítása a setState hívása nélkül. A fejlesztő _count++-t ír és elvárja, hogy az UI frissüljön. A Flutter nem tudja automatikusan követni a mezőváltozásokat — explicit jelre van szüksége a setState-en keresztül. Ez alapvető különbség az olyan reaktív keretrendszerektől, mint a Vue.js, ahol az adatváltozás automatikusan frissítést triggerel.

Negyedik hiba — a setState hívása aszinkron callback-kel (async-lambda). Ahogy az aszinkronitásról szóló részben leírtuk, az await utáni változások nem kerülnek rögzítésre, ami nehezen reprodukálható hibákhoz vezet. Használjon szinkron callback-et és hívja a setState-et await után.

Megjegyzés a biztonságos setState-hez

  • Aszinkron callback-ekben mindig ellenőrizze a mounted-et
  • Ne hívja a setState-et build-en belül
  • Ne adjon át async-lambda-t a setState-nek
  • Ne módosítsa a State mezőket setState-en kívül
  • Ha több mezőt módosít — tegye ezt egy setState-ben

Gyakran Ismételt Kérdések

Mit csinál a setState() a Flutter-ben?

setState() értesíti a Flutter-t, hogy a StatefulWidget belső adatai megváltoztak és az UI-t újra kell építeni. A metódus fogad egy callback-et, szinkron módon végrehajtja, piszkosnak jelöli a widget-et és a build meghívását tervezi a következő képkockában.

Mi történik, ha nem hívom meg a setState-et a mező módosítása után?

Az UI nem frissül. A Flutter nem követi automatikusan a mezőváltozásokat. A mező értéke a memóriában megváltozik, de a widget az előző állapotban marad a szülő általi következő kényszerített újraépítésig.

Meghívható-e a setState a build-en belül?

Nem. Ez végtelen ciklushoz vezet: a build meghívja a setState-et, amely piszkosnak jelöli a widget-et és újra meghívja a build-et. A Flutter nem blokkolja az ilyen helyzetet — az alkalmazás StackOverflowError-ral összeomlik.

Hányszor hajtódik végre a build két egymást követő setState esetén?

A build egyszer hajtódik végre. A Flutter összegyűjti az összes dirty elemet és kötegelve építi újra a képkocka végén. A második setState az első feldolgozása előtt egyszerűen hozzáadja az elemet ugyanahhoz a dirty elemek listájához — nem történik ismételt build.

Mi az a mounted és miért fontos a setState számára?

mounted — egy logikai jelző, amely mutatja, hogy a widget még a fában van. Ha aszinkron művelet után a mounted ellenőrzése nélkül hívja meg a setState-et, és a widget már eltávolításra került — az alkalmazás összeomlik a „setState called after dispose” kivétellel.

Összefoglaló

  • setState() — State metódus, amely értesíti a Flutter-t az adatváltozásról és elindítja az UI újraépítését a következő képkockában
  • Működési mechanizmus — a callback szinkron végrehajtása, a State piszkosnak jelölése, az összes dirty elem kötegelt újraépítése a képkocka végén
  • Aszinkronitás — az async-callback-ek a setState-ben nem működnek; az await-nek kívül kell lennie, a setState-nek pedig az eredmény megérkezése után
  • mounted — kötelező ellenőrzés a setState előtt aszinkron műveletekben a kivétel megelőzésére
  • Optimalizálás — minimalizálja az újraépítési területet const gyermek widget-ekkel és helyezze át az animációkat AnimatedBuilder-be
  • Alternatívák — globális állapothoz használjon Riverpod, Bloc vagy Provider-t; tartsa meg a setState-et helyi adatokhoz
  • Szabály — ne hívja a setState-et build-en belül, ne adjon át async-lambda-t, mindig ellenőrizze a mounted-et

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