State: ce este, gestionarea stării și principiul de funcționare

Autor: IT Sectr Publicat: 2026-07-01 Timp de citire: 9 min

State — obiectul central de gestionare a datelor în Flutter, asociat cu StatefulWidget și responsabil pentru stocarea informațiilor modificabile și construirea interfeței. Conform documentației oficiale Flutter (Flutter.dev, 2026), State există pe tot parcursul ciclului de viață al widgetului și supraviețuiește reconstruirilor acestuia, asigurând consistența datelor între actualizările UI. Spre deosebire de widgetul însuși, State își poate modifica câmpurile și poate iniția reconstruirea prin apelarea setState.

Principalele

  • State — obiect care stochează datele modificabile ale StatefulWidget și gestionează reconstruirea acestuia prin setState
  • Ciclul de viață — State trece prin initState, didChangeDependencies, build, didUpdateWidget și dispose, fiecare etapă cu un scop clar
  • mounted — flag care indică că State se află încă în arborele de widgeturi și poate apela setState în siguranță
  • widget — referință la StatefulWidget asociat, accesibilă prin proprietatea State pentru citirea parametrilor părintelui
  • Izolare — State este izolat de alte State; pentru schimbul de date se folosesc InheritedWidget sau instrumente externe de gestionare a stării

Ce este State în Flutter?

State — este un obiect în arhitectura Flutter care stochează datele modificabile ale StatefulWidget și determină modul în care aceste date sunt afișate în interfață. Fiecare StatefulWidget la încorporarea în arbore creează exact un obiect State prin metoda createState. State există independent de widget: dacă părintele reconstruiește StatefulWidget cu parametri noi, State rămâne același și primește widgetul actualizat prin proprietatea widget.

Conform Flutter Architectural Overview (Google, 2026), separarea Widget și State este o decizie arhitecturală conștientă, care permite frameworkului să reutilizeze elementele arborelui. Widgetul (descriere ușoară) poate fi creat și distrus de multiple ori, dar State (obiect greu cu date) rămâne în memorie cât timp elementul se află în arbore. Aceasta previne pierderea datelor la reconstruiri frecvente ale widgeturilor părinte.

State implementează interfața StatefulWidget prin generic: class _MyState extends State<MyWidget>. Genericul leagă State de un tip specific de StatefulWidget, asigurând acces tip-sigur la câmpurile sale prin proprietatea widget.

Unde este stocat State?

Obiectul State este stocat în StatefulElement — stratul intermediar între Widget și RenderObject. StatefulElement creează State prin createState, păstrează referința la acesta și transmite State ca proprietar. Elementul este distrus doar când widgetul este eliminat din arbore — până atunci State trăiește în memorie.

Ciclul de viață al State

Ciclul de viață al State este determinist și constă dintr-o succesiune strictă de apeluri. Înțelegerea acestei succesiuni este baza lucrului corect cu resursele și prevenirii scurgerilor de memorie.

initState — inițializare

initState este apelat primul la crearea State. În această metodă se inițializează controllere, abonamente la fluxuri de date, temporizatoare și valorile inițiale ale câmpurilor. Apelarea super.initState() în prima linie este obligatorie. În etapa initState, arborele de widgeturi nu este încă complet montat, deci metode precum MediaQuery.of(context) pot funcționa incorect.

didChangeDependencies

didChangeDependencies este apelat după initState și la fiecare modificare a dependențelor InheritedWidget. Exact aici, nu în initState, trebuie apelat MediaQuery.of(context) sau Theme.of(context), deoarece în acest moment arborele este deja montat. Această metodă este de asemenea apelată dacă widgetul este mutat într-un alt context unde InheritedWidget oferă valori diferite.

build — construirea UI

build — metoda principală a State, care returnează arborele de widgeturi. Apelată după initState, după didChangeDependencies și după fiecare setState. Metoda build nu trebuie să aibă efecte secundare — ea doar descrie interfața pe baza valorilor curente ale câmpurilor State.

didUpdateWidget

didUpdateWidget este apelat când părintele reconstruiește StatefulWidget cu parametri noi. State obține acces la widgetul vechi prin oldWidget și poate să îl compare cu cel nou. Dacă parametrii s-au schimbat, se poate actualiza starea, încărca date noi sau reporni animația.

dispose — eliberarea resurselor

dispose — metoda finală în care sunt eliberate toate resursele: controllere, abonamente, temporizatoare. După dispose, State este marcat ca mort: mounted returnează false, apelarea setState aruncă o excepție. Apelarea super.dispose() în ultima linie a metodei este obligatorie.

MetodăCând este apelatăsuper obligatoriu
initStateLa crearea StateDa, în prima linie
didChangeDependenciesDupă initState și la schimbarea InheritedWidgetDa
buildDupă initState, didChangeDependencies, setStateNu
didUpdateWidgetLa un widget nou de la părinteDa
setStateLa apelul dezvoltatoruluiNu
disposeLa eliminarea din arboreDa, în ultima linie

Cum funcționează State?

Mecanismul de funcționare al State se bazează pe trei principii cheie: asocierea cu Element, reactivitatea prin setState și accesul la părinte prin proprietatea widget. Când Flutter construiește arborele de elemente și întâlnește StatefulElement, apelează createState al widgetului asociat. State-ul creat este stocat în element și există până când elementul este eliminat.

La apelarea setState, State se marchează ca „murdar„ (dirty) și planifică reconstruirea pentru următorul cadru. Important: setState nu apelează build imediat — doar înregistrează necesitatea reconstruirii. Flutter colectează toate elementele murdare din cadrul curent și le reconstruiește în lot, ceea ce optimizează performanța. După apelarea build, State revine la starea „curat„ (clean).

Proprietatea widget permite State să citească parametrii transmiși constructorului StatefulWidget. Deoarece StatefulWidget este imuabil (ca StatelessWidget), câmpurile sale nu se schimbă — la modificarea parametrilor, părintele creează un widget nou, iar State îl primește prin didUpdateWidget. Aceasta garantează că State lucrează întotdeauna cu datele actualizate ale părintelui.

Exemple de cod în Dart

Exemplul de bază State cu un câmp modificat de un temporizator. Demonstrează initState, setState și dispose:

dart
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 secunde au trecut');
  }
}

Exemplu cu utilizarea proprietății widget pentru accesul la parametrii părintelui și reacția la modificările lor prin didUpdateWidget:

dart
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('Salut, $_displayName!');
  }
}

În al doilea exemplu, State urmărește modificarea parametrului de intrare name și reformatează afișarea doar la schimbarea reală. Fără verificarea widget.name != oldWidget.name, metoda ar fi apelată la fiecare reconstruire a părintelui, chiar dacă numele nu s-a schimbat — o muncă inutilă pentru framework.

State vs StatefulWidget

State și StatefulWidget sunt două clase diferite în arhitectura Flutter, cu roluri diferite. StatefulWidget — este o învelitoare ușoară imuabilă care descrie configurația widgetului și creează State. State — este un obiect greu care stochează date modificabile, gestionează abonamentele și construiește UI. Această separare permite Flutter să distrugă și să creeze widgeturi fără a pierde starea.

Toate câmpurile StatefulWidget trebuie să fie final și setate în constructor — ele nu se schimbă după creare. State, dimpotrivă, poate modifica oricând câmpurile sale, dar toate modificările trebuie precedate de apelarea setState, pentru ca Flutter să afle despre necesitatea reconstruirii. Aceasta este diferența cheie: StatefulWidget este „ce să arăți„, State — „cum să arăți și ce date să folosești„.

Conform Flutter source code analysis (Flutter SDK, 2026), StatefulWidget conține un singur câmp obligatoriu — createState, în timp ce State are acces la BuildContext, poate să se aboneze la fluxuri, să gestioneze animații și controllere. Se recomandă menținerea StatefulWidget cât mai simplu, transferând toată logica în State.

De ce StatefulWidget nu poate fi State?

Separarea Widget și State — o decizie arhitecturală care asigură imutabilitatea configurației. Dacă StatefulWidget ar stoca el însuși starea, la fiecare reconstruire a părintelui starea s-ar pierde. Extrăgând starea într-un obiect separat, Flutter garantează că datele supraviețuiesc reconstruirilor, iar widgeturile rămân ușoare și comparabile.

Gestionarea stării între widgeturi

Obiectul State este izolat — nu are acces direct la State-ul altor widgeturi. Pentru schimbul de date între widgeturi se folosesc InheritedWidget sau instrumente externe de gestionare a stării: Provider, Riverpod, Bloc, Redux. Fiecare abordare rezolvă problema în felul său: InheritedWidget funcționează prin arborele de widgeturi, Provider — prin containerul DI, Bloc — prin fluxuri de evenimente.

Alegerea instrumentului depinde de amploarea proiectului. Pentru o aplicație mică, sunt suficiente InheritedWidget și State local. Pentru un proiect mediu și mare, se recomandă Riverpod sau Bloc — ele asigură testabilitate, predictibilitate și separarea logicii de UI. State în acest caz este folosit doar pentru datele locale ale widgetului (focus, scroll, animație).

Conform Flutter Community Survey 2025 (Flutter Foundation, decembrie 2025), Riverpod este cea mai populară soluție pentru gestionarea stării în proiecte noi (38%), urmată de Bloc (31%) și Provider (22%). Toate trei instrumentele sunt compatibile cu State și nu necesită renunțarea la ciclul de viață standard.

Stare locală vs globală

  • Locală — în State-ul widgetului specific (poziția scroll-ului, starea focusului)
  • Globală — în stocarea externă (datele utilizatorului, setări, cache)
  • Regula: dacă datele sunt folosite doar de un widget — păstrați în State
  • Dacă datele sunt folosite de 2+ widgeturi — mutați în Riverpod/Bloc/Provider

Greșeli tipice

Prima greșeală — a uita să verificați mounted înainte de setState într-un callback asincron. Când widgetul a fost eliminat din arbore (de exemplu, utilizatorul a părăsit ecranul), dar operația asincronă (cererea HTTP) încă se execută, după finalizarea ei State este deja mort. Apelarea setState într-un State mort aruncă o excepție. Verificarea if (mounted) setState(...) rezolvă problema.

A doua greșeală — inițializarea dependențelor InheritedWidget în initState în loc de didChangeDependencies. În initState contextul nu este încă montat, deci MediaQuery.of(context) va arunca o excepție. Toate dependențele de InheritedWidget trebuie configurate în didChangeDependencies sau în build.

A treia greșeală — mutarea câmpurilor fără apelarea setState. Dacă dezvoltatorul modifică un câmp al State fără setState, Flutter nu va afla despre modificare și UI nu se va actualiza. De exemplu: _list.add(item) fără setState((){}) ulterior va modifica lista, dar ecranul va rămâne același.

Verificarea mounted înainte de setState

Modelul de siguranță pentru operații asincrone în State:

dart
Future<void> _fetchData() async {
  final data = await ApiService.fetch();
  if (mounted) {
    setState(() => _data = data);
  }
}

Verificarea mounted garantează că setState este apelat doar pentru un State viu, prevenind excepția „setState called after dispose„.

Întrebări frecvente

Prin ce diferă State de StatefulWidget?

StatefulWidget — configurația imuabilă a widgetului, iar State — un obiect modificabil care stochează date și gestionează ciclul de viață. Widgetul poate fi recreat, State — nu. StatefulWidget creează State prin createState.

Câte obiecte State se creează pentru un StatefulWidget?

Exact unul. Metoda createState este apelată o singură dată la prima încorporare a StatefulWidget în arbore. Chiar dacă părintele se reconstruiește de multiple ori, obiectul State rămâne același, până când se schimbă tipul sau Key-ul widgetului.

Ce este mounted în State?

mounted — un flag boolean care arată dacă State se află în arborele de widgeturi. După apelarea dispose, mounted devine false. Folosit pentru verificare înainte de setState în callback-uri asincrone, pentru a evita excepția.

Se poate folosi State fără StatefulWidget?

Nu. State este întotdeauna legat de un StatefulWidget specific prin generic: State<T extends StatefulWidget>. Crearea State direct, fără asociere cu un widget, este imposibilă arhitectural.

Ce se întâmplă dacă apelez setState în dispose?

Se aruncă o excepție: „setState called after dispose„. După apelarea dispose, State este considerat mort și orice încercare de a reconstrui UI prin setState este interzisă. Soluția — verificați mounted înainte de fiecare setState.

Rezumat

  • State — obiect de gestionare a datelor StatefulWidget, stochează câmpuri modificabile și inițiază reconstruirea UI prin setState
  • Ciclul de viață include metodele obligatorii initState, didChangeDependencies, build, didUpdateWidget și dispose, fiecare cu scopul său
  • mounted — un flag critic de siguranță care previne apelarea setState după eliminarea widgetului din arbore
  • widget — proprietatea State pentru accesul la parametrii StatefulWidget asociat, actualizată prin didUpdateWidget
  • Izolare — State nu are acces la alte State; interacțiunea între widgeturi se realizează prin InheritedWidget sau instrumente externe
  • setState — nu apelează build imediat, ci doar marchează State ca murdar pentru reconstruire în următorul cadru
  • Regula — folosiți State pentru datele locale ale widgetului; starea globală mutați în straturi externe (Riverpod, Bloc)

Vom dezvolta o aplicație mobilă la cheie

IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.

Discutați proiectul

Citiți și