FutureBuilder — шта је то, рад са Future у Flutter-у

Аутор: IT Sectr Објављено: 2026-07-02 Време читања: 8 мин

FutureBuilder — је виџет у Flutter-у који аутоматски обнавља свој интерфејс на основу тренутног стања AsyncSnapshot-а, добијеног из прослеђеног Future-а. За разлику од ручног позивања setState након await, FutureBuilder пружа декларативни приступ: претплаћује се на Future при првом рендеровању и позива builder функцију при свакој промени стања — учитавање, грешка или готови подаци. Према Flutter API Reference (2026), FutureBuilder је посебно користан за учитавање података из мреже, читање из базе података и све асинхроне операције где UI треба да прикаже индикатор учитавања, поруку о грешци или готов садржај.

Главне тачке

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

Шта је FutureBuilder у Flutter-у

FutureBuilder — је уграђени Flutter виџет из пакета widgets, који прима Future<T> и builder функцију. Када се стање Future-а промени (извршава се, завршен са подацима, завршен са грешком) FutureBuilder аутоматски обнавља UI, позивајући builder са новим AsyncSnapshot-ом. Ово елиминише потребу за ручним управљањем стањем учитавања путем setState-а и заставица.

За разлику од StreamBuilder-а, који ради са токовима података (Stream), FutureBuilder је намењен за једнократне асинхроне операције: HTTP захтев, читање из датотеке, упит бази података. FutureBuilder сам управља претплатом на Future: при првом прављењу покреће Future и прати његов завршетак. При уништењу виџета, FutureBuilder не отказује Future — то је одговорност програмера.

Према Flutter Cookbook (2026), FutureBuilder се препоручује за случајеве када се асинхрона операција покреће једном при иницијализацији екрана. За понављајуће операције или токове података користите StreamBuilder. Оба виџета праде исти образац Reactive UI, али FutureBuilder је оптимизован за једнократне захтеве.

Како FutureBuilder ради испод хаубе

Унутрашња имплементација FutureBuilder-а се претплаћује на Future путем Future.then и catchError. При покретању, FutureBuilder поставља connectionState на ConnectionState.waiting и позива builder са празним подацима. При успешном завршетку, connectionState се мења у ConnectionState.done са подацима. При грешци, snapshot.error се попуњава објектом грешке. Свака промена покреће обнављање виџета.

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('Корисници')),
      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('Грешка: ${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). Ако се родитељски виџет обнавља, FutureBuilder се такође обнавља. Да бисте спречили поновне позиве, уверите се да се Future креира ван build методе — иначе сваки позив build ствара нови Future.

Како спречити поновни захтев при обнављању?

Сачувајте Future у пољу StatefulWidget-а (у initState) или користите мемоизацију. Ако се Future креира унутар build методе, сваки позив build ће креирати нови Future, а FutureBuilder ће поново покренути асинхрону операцију. За StatelessWidget користите пакет cached_future или keep-alive виџете да би се 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 виџет за декларативну изградњу 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. године. Саветоваћемо вас и предложити најбоље решење.

Разговарајте о пројекту

Прочитајте такође