FutureBuilder — какво е това, работа с Future в Flutter

Автор: IT Sectr Публикувано: 2026-07-02 Време за четене: 8 мин

FutureBuilder — е widget във Flutter, който автоматично преизгражда интерфейса си въз основа на текущото състояние на AsyncSnapshot, получено от предадения Future. За разлика от ръчното извикване на setState след await, FutureBuilder предоставя декларативен подход: абонира се за Future при първото рендиране и извиква builder функцията при всяка промяна на състоянието — зареждане, грешка или готови данни. Според Flutter API Reference (2026), FutureBuilder е особено полезен за зареждане на данни от мрежа, четене от база данни и всякакви асинхронни операции, където UI трябва да показва индикатор за зареждане, съобщение за грешка или готово съдържание.

Основни точки

  • FutureBuilder — Flutter widget за изграждане на UI на базата на състоянието на Future чрез AsyncSnapshot (none, waiting, active, done)
  • AsyncSnapshot — обект, съдържащ текущото състояние на асинхронната операция: connectionState, data и error
  • builder — callback функция, извиквана при всяка промяна на състоянието на Future за преизграждане на UI
  • Обработка на грешки — AsyncSnapshot.hasError позволява показване на резервен интерфейс при неуспех на асинхронна операция
  • ConnectionState — enum с четири стойности: none (няма операция), waiting (изчакване), active (поток), done (завършено)

Какво е FutureBuilder във Flutter

FutureBuilder — е вграден Flutter widget от пакета widgets, който приема Future<T> и builder функция. Когато състоянието на Future се промени (изпълнява се, завършен с данни, завършен с грешка) FutureBuilder автоматично преизгражда UI, извиквайки builder с нов AsyncSnapshot. Това елиминира необходимостта от ръчно управление на състоянието на зареждане чрез setState и флагове.

За разлика от StreamBuilder, който работи с потоци от данни (Stream), FutureBuilder е предназначен за еднократни асинхронни операции: HTTP заявка, четене от файл, запитване към база данни. FutureBuilder сам управлява абонамента за Future: при първото изграждане стартира Future и проследява завършването му. При унищожаване на widget, FutureBuilder не отменя Future — това е отговорност на разработчика.

Според Flutter Cookbook (2026), FutureBuilder се препоръчва за случаи, когато асинхронната операция се стартира веднъж при инициализация на екрана. За повтарящи се операции или потоци от данни използвайте StreamBuilder. И двата widget следват един и същ модел Reactive UI, но FutureBuilder е оптимизиран за еднократни заявки.

Как FutureBuilder работи под капака

Вътрешната имплементация на FutureBuilder се абонира за Future чрез Future.then и catchError. При стартиране FutureBuilder задава connectionState на ConnectionState.waiting и извиква builder с празни данни. При успешно завършване connectionState се променя на ConnectionState.done с данни. При грешка snapshot.error се попълва с обекта на грешката. Всяка промяна задейства преизграждане на widget.

AsyncSnapshot: състояния и свойства

AsyncSnapshot — е контейнерен обект, който FutureBuilder предава на builder функцията при всяка промяна на състоянието. Той съдържа цялата информация за текущия статус на асинхронната операция: дали зареждането продължава, какви данни са получени, дали е възникнала грешка. Разбирането на AsyncSnapshot е ключът към правилното изграждане на UI с FutureBuilder.

СвойствоТипОписание
connectionStateConnectionStateТекущо състояние на връзката (none, waiting, active, done)
dataT?Данни, получени от Future (null до завършване или при грешка)
errorObject?Обект на грешка, ако Future е завършил с изключение
hasDatabooltrue, ако data не е null и състоянието е ConnectionState.done
hasErrorbooltrue, ако Future е завършил с грешка

ConnectionState: четири състояния на асинхронна операция

Enum ConnectionState определя фазата на асинхронната операция. None — начално състояние, когато Future все още не е стартиран (използва се рядко, обикновено при първо изграждане без initialData). Waiting — Future се изпълнява, данните все още не са получени. Active — използва се само от StreamBuilder за потоци с частични данни. Done — Future е завършен, данните са достъпни чрез snapshot.data или грешката чрез snapshot.error.

Правилната обработка на всички състояния на AsyncSnapshot в builder функцията е задължително изискване за продуктиционен код. Ако не обработите състоянието waiting, потребителят ще види празен екран по време на зареждане. Ако не обработите hasError, потребителят ще получи Exception без обяснение. Препоръчителен модел: проверка на hasError → проверка на hasData → показване на зареждане по подразбиране.

Модели на използване на FutureBuilder

FutureBuilder може да се използва в няколко стандартни модела, всеки от които решава конкретна задача. Нека разгледаме основните сценарии: зареждане на данни при инициализация, зареждане с кеширане, паралелни заявки и обработка на грешки с повторение.

Зареждане на данни при инициализация на екрана

Най-честият модел — FutureBuilder в build метода на StatefulWidget или StatelessWidget. Future се предава от initState или се създава директно в build. Важно е да не създавате Future в build метода при всяко преизграждане — това води до повторни заявки. Използвайте Future, запазено в полето на State.

Зареждане с кеширане и обновяване

За предотвратяване на повторни заявки, FutureBuilder може да се комбинира с CachedNetworkImage или локален кеш. След първото зареждане данните се запазват в паметта или SharedPreferences, а FutureBuilder показва кешираните данни незабавно, паралелно ги обновявайки от мрежата. Това подобрява UX чрез незабавен отговор.

Според pub.dev (2026), кеширането е особено важно за изображения и списъци с данни. FutureBuilder с CachedNetworkImageProvider автоматично показва кешираното изображение, а при липсата му — индикатор за зареждане с последващо показване на изтегления файл.

FutureBuilder vs setState: какво да изберем

FutureBuilder и ръчно управление на състоянието чрез setState — два подхода към асинхронния UI във Flutter. Всеки има своите предимства и ограничения. Изборът зависи от сложността на екрана и броя на асинхронните операции.

FutureBuilder печели с простотата си: не е необходимо да декларирате полета за състояние на зареждане, данни и грешка — всичко се управлява чрез AsyncSnapshot. Идеален е за прости екрани с една асинхронна операция (една HTTP заявка, четене от база данни). Въпреки това, при 5+ асинхронни операции на един екран, FutureBuilder създава прекомерно влагане — образува се „пирамида" от вложени FutureBuilder-и.

setState с ръчни флагове на състоянието дава повече контрол и четимост при сложна логика. За екрани с множество зависими заявки (зареди потребител → зареди неговите поръчки → зареди детайли на поръчка) е по-добре да използвате setState с ChangeNotifier или Bloc. Според Flutter State Management Guide (2026), за сложни сценарии се препоръчва използването на Riverpod или Bloc вместо FutureBuilder, тъй като те осигуряват по-добро разделение на логиката и презентацията.

Пример за FutureBuilder със зареждане на данни от мрежа

Нека разгледаме практически пример за FutureBuilder за зареждане на списък с потребители от REST API. Кодът демонстрира правилната обработка на трите състояния на AsyncSnapshot: зареждане, грешка и готови данни.

dart
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('Users')),
      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('Error: ${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());
        },
      ),
    );
  }
}

В примера FutureBuilder обработва и трите състояния. При грешка се показва икона със съобщение за грешка. При успешно зареждане — ListView с аватари и имена. По време на зареждане — CircularProgressIndicator. Future е декларирано като поле на класа, което предотвратява повторно извикване при преизграждане. Този модел покрива 90% от сценариите за използване на FutureBuilder в мобилни приложения.

Често задавани въпроси

Защо FutureBuilder извиква builder няколко пъти?

FutureBuilder извиква builder при всяка промяна на състоянието на Future: първия път при създаване (connectionState: none или waiting), втория път при завършване (connectionState: done). Ако родителският widget се преизгради, FutureBuilder също се преизгражда. За да предотвратите повторни извиквания, уверете се, че Future се създава извън build метода — иначе всяко извикване на build създава нов Future.

Как да предотвратя повторна заявка при преизграждане?

Запазете Future в полето на StatefulWidget (в initState) или използвайте мемоизация. Ако Future се създава вътре в build метода, всяко извикване на build ще създаде нов Future и FutureBuilder ще рестартира асинхронната операция. За StatelessWidget използвайте пакета cached_future или keep-alive widget-ове, така че Future да се изпълни веднъж независимо от преизгражданията.

Как се различава FutureBuilder от StreamBuilder?

FutureBuilder е предназначен за еднократни асинхронни операции (една HTTP заявка, едно четене от база данни). StreamBuilder работи с потоци от данни, които могат да излъчват множество стойности във времето (чат, актуализации на цени, геолокация). StreamBuilder поддържа ConnectionState.active за частични данни, докато FutureBuilder поддържа само waiting и done.

Как да използвам FutureBuilder с няколко Future?

За няколко паралелни Future използвайте Future.wait и предайте резултата на един FutureBuilder. Future.wait приема списък от Future и връща Future<List> — когато всички Future завършат, builder получава масив от резултати. За последователни заявки използвайте верига от Future.then в рамките на едно Future или вложени FutureBuilder (по-малко четимо). Алтернатива — пакетът riverpod с AsyncValue за множество асинхронни състояния.

Как да отменя Future при излизане от екрана?

FutureBuilder не отменя Future автоматично. За отмяна използвайте CancelableOperation от пакета async или собствен механизъм чрез флаг cancelled в State. В dispose() задайте флага и след завършване на Future го проверете преди извикване на setState. Алтернативно използвайте пакета riverpod с AutoDispose, който автоматично отменя асинхронни операции при излизане от екрана.

Обобщение

  • FutureBuilder — Flutter widget за декларативно изграждане на UI на базата на състоянието на Future чрез AsyncSnapshot (waiting, done, error)
  • AsyncSnapshot — контейнер с connectionState, data и error; задължителен за правилна обработка на всички състояния на асинхронна операция
  • builder — callback с три клона: hasError (показване на грешка), hasData (показване на данни), default (индикатор за зареждане)
  • FutureBuilder vs setState — FutureBuilder е по-прост за една операция, setState с Bloc/Riverpod е по-добър за сложна логика с множество заявки
  • Предотвратяване на повторни заявки — Future трябва да бъде поле на State, не го създавайте в build метода за да избегнете рестартиране при всяко преизграждане
  • Отмяна на Future — FutureBuilder не отменя Future при dispose; използвайте CancelableOperation или флаг за отмяна за предотвратяване на setState след унищожаване
  • Множество Future — за паралелни заявки използвайте Future.wait с един FutureBuilder; за последователни — вериги в едно Future

Ще разработим мобилно приложение под ключ

IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.

Обсъдете проекта

Прочетете също