FutureBuilder — este un widget în Flutter care reconstruiește automat interfața pe baza stării curente a AsyncSnapshot, obținut din Future-ul transmis. Spre deosebire de apelarea manuală a setState după await, FutureBuilder oferă o abordare declarativă: se abonează la Future la prima randare și apelează funcția builder la fiecare schimbare de stare — încărcare, eroare sau date gata. Conform Flutter API Reference (2026), FutureBuilder este util în special pentru încărcarea datelor din rețea, citirea din baza de date și orice operații asincrone unde UI trebuie să afișeze un indicator de încărcare, un mesaj de eroare sau conținut gata.
Principalele puncte
FutureBuilder — este un widget încorporat Flutter din pachetul widgets, care primește Future<T> și o funcție builder. La schimbarea stării Future (se execută, finalizat cu date, finalizat cu eroare) FutureBuilder reconstruiește automat UI, apelând builder cu noul AsyncSnapshot. Aceasta elimină necesitatea gestionării manuale a stării de încărcare prin setState și flag-uri.
Spre deosebire de StreamBuilder, care lucrează cu fluxuri de date (Stream), FutureBuilder este destinat operațiilor asincrone unice: cerere HTTP, citire din fișier, interogare bază de date. FutureBuilder gestionează singur abonarea la Future: la prima construire pornește Future și urmărește finalizarea acestuia. La distrugerea widgetului, FutureBuilder nu anulează Future — aceasta este responsabilitatea dezvoltatorului.
Conform Flutter Cookbook (2026), FutureBuilder este recomandat pentru cazurile în care operația asincronă se lansează o dată la inițializarea ecranului. Pentru operații repetitive sau fluxuri de date, utilizați StreamBuilder. Ambele widgeturi urmează același pattern Reactive UI, dar FutureBuilder este optimizat pentru cereri unice.
Implementarea internă a FutureBuilder se abonează la Future prin Future.then și catchError. La pornire, FutureBuilder setează connectionState la ConnectionState.waiting și apelează builder cu date goale. La finalizarea cu succes, connectionState se schimbă în ConnectionState.done cu date. La eroare, snapshot.error este populat cu obiectul de eroare. Fiecare schimbare declanșează reconstruirea widgetului.
AsyncSnapshot — este un obiect-container pe care FutureBuilder îl transmite funcției builder la fiecare schimbare de stare. Conține toate informațiile despre statusul curent al operației asincrone: dacă încărcarea este în curs, ce date au fost primite, dacă a apărut o eroare. Înțelegerea AsyncSnapshot este cheia construirii corecte a UI cu FutureBuilder.
| Proprietate | Tip | Descriere |
|---|---|---|
| connectionState | ConnectionState | Starea curentă a conexiunii (none, waiting, active, done) |
| data | T? | Datele primite de la Future (null până la finalizare sau la eroare) |
| error | Object? | Obiectul de eroare dacă Future s-a finalizat cu excepție |
| hasData | bool | true dacă data nu este null și starea este ConnectionState.done |
| hasError | bool | true dacă Future s-a finalizat cu eroare |
Enum-ul ConnectionState determină etapa operației asincrone. None — starea inițială când Future nu a fost încă lansat (folosit rar, de obicei la prima construire fără initialData). Waiting — Future se execută, datele nu au fost încă primite. Active — folosit doar de StreamBuilder pentru fluxuri cu date parțiale. Done — Future s-a finalizat, datele sunt disponibile prin snapshot.data sau eroarea prin snapshot.error.
Gestionarea corectă a tuturor stărilor AsyncSnapshot în funcția builder — o cerință obligatorie pentru codul de producție. Dacă nu gestionați starea waiting, utilizatorul va vedea un ecran gol în timpul încărcării. Dacă nu gestionați hasError, utilizatorul va primi o Exception fără explicație. Pattern-ul recomandat: verificare hasError → verificare hasData → implicit afișare încărcare.
FutureBuilder poate fi utilizat în mai multe pattern-uri standard, fiecare rezolvând o sarcină specifică. Să analizăm scenariile principale: încărcarea datelor la inițializare, încărcarea cu cache, cereri paralele și gestionarea erorilor cu reîncercare.
Cel mai comun pattern — FutureBuilder în metoda build a StatefulWidget sau StatelessWidget. Future este transmis din initState sau creat direct în build. Este important să nu creați Future în metoda build la fiecare reconstruire — aceasta duce la cereri repetate. Utilizați Future salvat în câmpul State.
Pentru a preveni cererile repetate, FutureBuilder poate fi combinat cu CachedNetworkImage sau cache local. După prima încărcare, datele sunt salvate în memorie sau SharedPreferences, iar FutureBuilder afișează datele din cache instantaneu, actualizându-le în paralel din rețea. Aceasta îmbunătățește UX prin răspuns instantaneu.
Conform pub.dev (2026), cache-ul este deosebit de relevant pentru imagini și liste de date. FutureBuilder cu CachedNetworkImageProvider afișează automat imaginea din cache, iar în lipsa acesteia — un indicator de încărcare cu afișarea ulterioară a fișierului descărcat.
FutureBuilder și gestionarea manuală a stării prin setState — două abordări ale UI-ului asincron în Flutter. Fiecare are avantajele și limitările sale. Alegerea depinde de complexitatea ecranului și numărul de operații asincrone.
FutureBuilder câștigă prin simplitate: nu trebuie declarate câmpuri pentru starea de încărcare, date și eroare — totul este gestionat prin AsyncSnapshot. Este ideal pentru ecrane simple cu o singură operație asincronă (o cerere HTTP, citire din bază de date). Totuși, la 5+ operații asincrone pe un ecran, FutureBuilder creează o cuibărire excesivă — se formează o „piramidă" de FutureBuilder-uri cuibărite.
setState cu flag-uri manuale de stare oferă mai mult control și lizibilitate în logica complexă. Pentru ecrane cu multiple cereri dependente (încărcare utilizator → încărcare comenzi → încărcare detalii comandă) este mai bine să folosiți setState cu ChangeNotifier sau Bloc. Conform Flutter State Management Guide (2026), pentru scenarii complexe se recomandă utilizarea Riverpod sau Bloc în loc de FutureBuilder, deoarece asigură o separare mai bună a logicii de prezentare.
Să analizăm un exemplu practic de FutureBuilder pentru încărcarea unei liste de utilizatori dintr-un REST API. Codul demonstrează gestionarea corectă a tuturor celor trei stări AsyncSnapshot: încărcare, eroare și date gata.
class UserListPage extends StatefulWidget {
const UserListPage({super.key});
@override
State<UserListPage> createState() => _UserListPageState();
}
class _UserListPageState extends State<UserListPage> {
final Future<List<User>> usersFuture = UserRepository().fetchUsers();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Utilizatori')),
body: FutureBuilder<List<User>>(
future: usersFuture,
builder: (context, AsyncSnapshot<List<User>> snapshot) {
if (snapshot.hasError) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.error_outline, size: 48, color: Colors.red),
const SizedBox(height: 16),
Text('Eroare: ${snapshot.error}'),
],
),
);
}
if (snapshot.hasData) {
final users = snapshot.data!;
return ListView.builder(
itemCount: users.length,
itemBuilder: (context, index) {
return ListTile(
leading: CircleAvatar(backgroundImage: NetworkImage(users[index].avatarUrl)),
title: Text(users[index].name),
subtitle: Text(users[index].email),
);
},
);
}
return const Center(child: CircularProgressIndicator());
},
),
);
}
}
În exemplu, FutureBuilder gestionează toate cele trei stări. La eroare se afișează o iconiță cu mesajul de eroare. La încărcare cu succes — ListView cu avataruri și nume. În timpul încărcării — CircularProgressIndicator. Future este declarat ca câmp al clasei, ceea ce previne re-apelarea la reconstruire. Acest pattern acoperă 90% din scenariile de utilizare a FutureBuilder în aplicații mobile.
Întrebări frecvente
FutureBuilder apelează builder la fiecare schimbare de stare a Future: prima dată la creare (connectionState: none sau waiting), a doua oară la finalizare (connectionState: done). Dacă widgetul părinte se reconstruiește, FutureBuilder se reconstruiește și el. Pentru a preveni apelurile repetate, asigurați-vă că Future este creat în afara metodei build — altfel fiecare apel build creează un nou Future.
Salvați Future în câmpul StatefulWidget (în initState) sau folosiți memoizare. Dacă Future este creat în interiorul metodei build, fiecare apel build va crea un nou Future, iar FutureBuilder va reporni operația asincronă. Pentru StatelessWidget, utilizați pachetul cached_future sau widget-uri keep-alive pentru ca Future să se execute o singură dată indiferent de reconstruiri.
FutureBuilder este destinat operațiilor asincrone unice (o cerere HTTP, o citire din bază de date). StreamBuilder lucrează cu fluxuri de date care pot emite multiple valori în timp (chat, actualizări de preț, geolocație). StreamBuilder suportă ConnectionState.active pentru date parțiale, iar FutureBuilder — doar waiting și done.
Pentru mai multe Future paralele, folosiți Future.wait și transmiteți rezultatul într-un singur FutureBuilder. Future.wait primește o listă de Future și returnează Future<List> — când toate Future-urile sunt finalizate, builder primește un array de rezultate. Pentru cereri secvențiale, folosiți un lanț Future.then în interiorul unui singur Future sau FutureBuilder-uri cuibărite (mai puțin lizibil). Alternativa — pachetul riverpod cu AsyncValue pentru stări asincrone multiple.
FutureBuilder nu anulează Future automat. Pentru anulare, folosiți CancelableOperation din pachetul async sau propriul mecanism prin flag-ul cancelled în State. În dispose() setați flag-ul, iar după finalizarea Future verificați-l înainte de a apela setState. Alternativ, folosiți pachetul riverpod cu AutoDispose, care anulează automat operațiile asincrone la ieșirea din ecran.
Rezumat
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.
Citiți și