StatefulWidget: ce este, ciclul de viață și principiul de funcționare

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

StatefulWidget — un widget Flutter cu stare modificabilă, care permite UI să reacționeze la acțiunile utilizatorului, evenimente asincrone și fluxuri de date. Conform documentației oficiale Flutter (Flutter.dev, 2026), StatefulWidget este utilizat pentru toate elementele interactive ale aplicației: formulare de introducere, animații, casete de selectare, comutatoare și ecrane care încarcă date din rețea. Spre deosebire de StatelessWidget, acesta creează un obiect State separat, care se păstrează pe întreg parcursul ciclului de viață și poate fi reconstruit fără a recrea widgetul în sine.

Principalele

  • StatefulWidget — un widget care își poate schimba starea în timpul funcționării, declanșând reconstruirea UI prin setState
  • Ciclul de viață — StatefulWidget trece prin etapele createState, initState, didChangeDependencies, build, didUpdateWidget, dispose
  • Obiectul State — un obiect separat care stochează starea și există independent de widget pe întreg parcursul vieții sale
  • setState — singurul mod legitim de a notifica Flutter despre necesitatea reconstruirii widgetului după modificarea datelor
  • Performanță — utilizarea excesivă a StatefulWidget crește consumul de memorie și timpul de randare

Ce este StatefulWidget?

StatefulWidget — este o clasă Flutter care își poate schimba starea ca răspuns la acțiunile utilizatorului, evenimente de sistem sau operații asincrone. Spre deosebire de StatelessWidget, StatefulWidget nu este afișat direct — el creează un obiect State care se ocupă de randare. Împărțirea în două clase (Widget și State) permite Flutter să reconstruiască UI fără a recrea widgetul în sine, oferind un avantaj semnificativ de performanță la actualizări frecvente.

Arhitectura StatefulWidget urmează modelul «separarea modificabilului de nemodificabil»: widgetul în sine rămâne imutabil (ca StatelessWidget), iar toată starea modificabilă este stocată într-un obiect State separat. Acest lucru permite Flutter să reutilizeze widgeturile, comparându-le după tip și Key, păstrând în același timp starea actuală între reconstruiri.

Conform Google (Flutter Architectural Overview, 2026), StatefulWidget este optim pentru scenariile în care starea se schimbă de mai multe ori pe durata vieții widgetului: câmpuri text, animații, temporizatoare, fluxuri de date, încărcări asincrone. Pentru inițializare unică, StatelessWidget este suficient.

Când este necesar StatefulWidget

StatefulWidget este obligatoriu atunci când widgetul trebuie să reacționeze la evenimente externe: apăsarea unui buton, finalizarea unei cereri HTTP, actualizarea datelor din baza de date, abonarea la WebSocket. De asemenea, este necesar pentru widgeturi cu animații, câmpuri text cu controllere și componente care gestionează focalizarea. Dacă widgetul doar afișează date și nu generează evenimente — utilizați StatelessWidget.

Structura internă

StatefulWidget constă din două clase: StatefulWidget propriu-zis (ușor, imutabil) și State (greu, modificabil). Framework-ul creează State prin metoda createState(), apelată o singură dată la încorporarea în arbore. State primește o referință la widget prin proprietatea widget și poate accesa câmpurile sale în orice moment al ciclului de viață.

Ciclul de viață al StatefulWidget

Ciclul de viață al StatefulWidget constă din șase etape principale, fiecare oferind o metodă suprascrisă pentru îndeplinirea sarcinilor specifice. Înțelegerea acestor etape este esențială pentru lucrul corect cu resursele și evitarea scurgerilor de memorie.

createState

createState — prima metodă a ciclului de viață, apelată la încorporarea StatefulWidget în arbore. Trebuie să returneze o nouă instanță a State asociată cu acest widget. Această metodă este apelată exact o dată pe toată durata vieții elementului. Este important să nu se execute operații grele aici — createState trebuie să fie cât mai ușor posibil.

initState

initState — este apelat imediat după crearea State, înainte de prima construcție a UI. Aici se execută: inițializarea controlerelor (TextEditingController, AnimationController), abonarea la fluxuri de date (StreamSubscription), configurarea temporizatoarelor și inițializarea inițială a câmpurilor. Conform documentației Flutter (Flutter.dev, 2026), în initState nu se poate apela BuildContext.of() — arborele nu este încă complet montat.

didChangeDependencies

didChangeDependencies — este apelat după initState și de fiecare dată când se modifică dependențele InheritedWidget. Acesta este locul potrivit pentru a apela MediaQuery.of(context) sau pentru a vă abona la Theme — valori care se pot schimba în timpul funcționării aplicației. Dacă widgetul utilizează InheritedWidget, logica de inițializare ar trebui să fie aici, nu în initState.

build și didUpdateWidget

build — metoda principală care returnează arborele de widgeturi. Este apelată după initState, după didChangeDependencies și după fiecare setState. didUpdateWidget este apelat când părintele se reconstruiește și transmite StatefulWidget cu parametri noi. Aici puteți compara câmpurile vechi și noi ale widgetului și, dacă este necesar, să actualizați starea.

dispose

dispose — etapa finală a ciclului de viață. Aici sunt eliberate toate resursele: anularea abonamentelor la fluxuri, ștergerea controlerelor, anularea temporizatoarelor. Neapelarea dispose duce la scurgeri de memorie. După dispose, State este considerat mort — apelarea setState în interiorul său aruncă o excepție.

Cum funcționează StatefulWidget?

Mecanismul de funcționare a StatefulWidget se bazează pe munca coordonată a trei entități: Widget (descriere ușoară), Element (strat intermediar) și State (depozit de date). Când Flutter întâlnește StatefulWidget în descriere, creează un StatefulElement care apelează createState și stochează referința la obiectul State. La reconstruirea părintelui, Flutter compară noul widget cu Elementul curent — dacă tipul și Key coincid, Elementul este actualizat, iar State rămâne același.

Starea se schimbă doar prin apelarea setState, care notifică framework-ul despre necesitatea reconstruirii. Este important de înțeles: setState nu modifică starea automat — marchează doar widgetul ca «murdar». Dezvoltatorul actualizează singur câmpurile State în callback-ul transmis către setState. După finalizarea callback-ului, Flutter apelează build și actualizează UI.

Conform echipei Dart/Flutter (Dart Language Specification, 2026), această separare garantează că toate modificările de stare au loc sincron înainte de apelarea build, eliminând situația în care UI afișează date parțial actualizate. Acesta este mecanismul cheie de consistență a interfeței în Flutter.

Exemple de cod în Dart

Să analizăm un StatefulWidget simplu — un contor de clicuri pe buton. Acesta demonstrează modelul de bază: crearea State, inițializarea câmpului în initState, modificarea prin setState:

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('Număr: $_count'),
        ElevatedButton(
          onPressed: _increment,
          child: const Text('Increment'),
        ),
      ],
    );
  }
}

Exemplu cu încărcare asincronă de date și gestionarea ciclului de viață. StatefulWidget încarcă date din rețea și afișează starea de încărcare:

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('Salut, ${_user!.name}');
  }
}

În al doilea exemplu, este important de remarcat: initState pornește o operație asincronă, dar metoda în sine nu este asincronă. Asincronicitatea este realizată prin async/await în interiorul metodei separate _loadUser, care actualizează starea prin setState după finalizarea cererii. Această abordare garantează că widgetul va afișa corect indicatorul de încărcare înainte de primirea datelor.

StatefulWidget vs StatelessWidget

Alegerea între StatefulWidget și StatelessWidget nu este doar o chestiune de prezență a stării. StatefulWidget oferă un ciclu de viață complet cu metodele initState, didChangeDependencies, didUpdateWidget și dispose, necesare pentru lucrul cu controllere, animații și fluxuri. StatelessWidget, la rândul său, nu are aceste metode și este întotdeauna mai ușor pentru framework.

Recomandarea echipei Flutter (Flutter docs, 2026) — minimizați numărul de StatefulWidget în aplicație, ridicând starea în sus în arbore (State Hoisting) sau utilizând soluții de gestionare a stării (Riverpod, Bloc, Provider). Fiecare StatefulWidget creează un obiect State care trăiește până la ștergerea elementului — cu cât mai multe astfel de widgeturi, cu atât mai mare este încărcarea memoriei.

CriteriuStatefulWidgetStatelessWidget
StareModificabilăNemodificabilă
Ciclu de viață6 etapeDoar build
Obiect StateCreat separatNu este necesar
setStateDisponibilIndisponibil
AbonamenteinitState/disposeNu sunt suportate
Constructor constLimitatComplet suportat
Consum de memorieMai mareMai mic

Performanță și optimizare

StatefulWidget necesită mai multe resurse decât StatelessWidget din cauza necesității de a crea și menține obiectul State. Cu toate acestea, utilizarea corectă a StatefulWidget nu duce la probleme de performanță dacă se respectă câteva reguli. În primul rând, evitați încuibarea profundă a StatefulWidget — fiecare nivel adaugă costuri suplimentare pentru traversarea arborelui. În al doilea rând, împărțiți StatefulWidget complex în mai multe widgeturi simple, fiecare responsabil pentru partea sa de stare.

Conform cercetării Flutter Performance (Flutter.dev, februarie 2026), cea mai frecventă cauză a scăderii FPS este apelarea setState în widgetul părinte, care reconstruiește toți descendenții, inclusiv StatelessWidget care nu și-au schimbat afișarea. Soluția — mutarea părții modificabile a UI într-un StatefulWidget separat, astfel încât setState să reconstruiască doar minimul de widgeturi necesare.

Utilizarea const în interiorul State este o altă tehnică importantă. Dacă widgeturile copil sunt declarate ca const, Flutter nu le va reconstrui la apelarea setState în părinte. Aceasta reduce încărcarea framework-ului și micșorează timpul de randare a cadrelor.

Evitați setState frecvente

Fiecare apel setState declanșează o reconstruire completă a widgetului. Dacă starea se schimbă cu frecvență ridicată (de exemplu, animație sau flux de date), luați în considerare utilizarea AnimatedBuilder, ValueListenableBuilder sau StreamBuilder în locul apelării manuale a setState. Aceste widgeturi optimizează reconstruirea, actualizând doar acea parte a UI care s-a schimbat efectiv.

Erori tipice

Prima eroare tipică cu StatefulWidget — apelarea setState după dispose. Când widgetul este șters din arbore, State este considerat mort și orice apel setState aruncă excepția «setState called after dispose». Cel mai adesea, acest lucru se întâmplă atunci când o operație asincronă se finalizează după ștergerea widgetului. Soluția — verificarea indicatorului mounted înainte de apelarea setState sau anularea operațiilor asincrone în dispose.

A doua eroare — executarea de calcule grele în metoda build. Deoarece build este apelat la fiecare setState și la fiecare reconstruire a părintelui, toate calculele trebuie să fie cât mai ușoare posibil. Dacă trebuie să efectuați o operație consumatoare de resurse — mutați-o într-un Isolate separat sau stocați rezultatul într-un câmp State.

A treia eroare — lipsa apelării super.initState() și super.dispose(). Suprascriind aceste metode, dezvoltatorul este obligat să apeleze implementarea părintelui. Dacă acest lucru nu se face, framework-ul nu va putea gestiona corect starea Element, ceea ce va duce la erori dificil de depistat.

Recomandări pentru evitarea erorilor

  • Verificați întotdeauna mounted înainte de setState în callback-uri asincrone
  • Nu uitați să apelați super.initState() și super.dispose()
  • Nu faceți cereri HTTP direct în build — utilizați initState
  • Anulați toate abonamentele în dispose
  • Utilizați un număr minim de StatefulWidget în proiect

întrebări frecvente

Cu ce se deosebește StatefulWidget de StatelessWidget?

StatefulWidget își poate schimba starea prin setState, are un ciclu de viață (initState, dispose) și creează un obiect State separat. StatelessWidget nu poate schimba starea și nu are metode ale ciclului de viață — doar afișează datele primite.

De câte ori este apelat createState?

createState este apelat exact o dată pentru fiecare instanță a StatefulElement. Chiar dacă părintele se reconstruiește de mai multe ori, atâta timp cât tipul și Key-ul widgetului nu se schimbă, createState nu este apelat — se utilizează obiectul State existent.

Ce se întâmplă dacă nu se apelează dispose?

Resursele nu vor fi eliberate: controllerele vor continua să funcționeze în fundal, abonamentele la fluxuri vor rămâne active, temporizatoarele nu vor fi anulate. Acest lucru duce la scurgeri de memorie și poate provoca apelarea setState după dispose, ceea ce aruncă o excepție.

Poate StatefulWidget să fie const?

Da, constructorul StatefulWidget poate fi const. Cu toate acestea, acest lucru nu oferă același beneficiu ca pentru StatelessWidget — obiectul State va fi oricum creat la prima încorporare. const afectează doar widgetul în sine (ambalajul ușor), nu și State.

De ce este necesară metoda didUpdateWidget?

didUpdateWidget este apelat când părintele transmite StatefulWidget cu parametri noi. Acest lucru este necesar pentru a sincroniza starea cu noile date — de exemplu, dacă s-a schimbat userId în parametri, trebuie încărcat profilul noului utilizator.

Rezumat

  • StatefulWidget — un widget cu stare modificabilă, care utilizează un obiect State separat pentru stocarea datelor și gestionarea ciclului de viață
  • Ciclul de viață constă din createState, initState, didChangeDependencies, build, didUpdateWidget și dispose, fiecare având propriul scop
  • setState — singurul mod legitim de a notifica framework-ul despre schimbarea stării, după care build este apelat automat
  • mounted — un indicator care trebuie verificat înainte de apelarea setState în operații asincrone pentru a evita excepția după dispose
  • Performanță — StatefulWidget necesită mai multe resurse decât StatelessWidget; se recomandă minimizarea numărului lor prin mutarea stării în straturi externe
  • Widgeturile copil const în interiorul State permit reducerea volumului de reconstruire la apelarea setState, îmbunătățind performanța
  • Alegerea corectă — utilizați StatefulWidget doar atunci când widgetul trebuie să gestioneze date modificabile sau operații asincrone

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