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 — widget Flutter για την κατασκευή 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 — είναι ένα ενσωματωμένο widget του Flutter από το πακέτο 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. Και τα δύο widgets ακολουθούν το ίδιο πρότυπο 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 εμφανίζει άμεσα τα προφυλαγμένα δεδομένα, ενώ παράλληλα τα ενημερώνει από το δίκτυο. Αυτό βελτιώνει την εμπειρία χρήστη με άμεση απόκριση.

Σύμφωνα με το pub.dev (2026), η προφυλαξή είναι ιδιαίτερα σημαντική για εικόνες και λίστες δεδομένων. Το FutureBuilder με CachedNetworkImageProvider εμφανίζει αυτόματα την προφυλαγμένη εικόνα, και σε περίπτωση απουσίας της — δείκτη φόρτωσης με επακόλουθη εμφάνιση του ληφθέντος αρχείου.

FutureBuilder vs setState: τι να επιλέξουμε

FutureBuilder και η μανυαλική διαχείριση κατάστασης μέσω setState — δύο προσεγγίσεις στο ασύγχρονο UI στο Flutter. Κάθε μία έχει τα πλεονεκτήματα και τους περιορισμούς της. Η επιλογή εξαρτάται από την πολυπλοκότητα της οθόνης και τον αριθμό των ασύγχρονων λειτουργιών.

Το FutureBuilder κερδίζει σε απλότητα: δεν χρειάζεται να δημιουργήσετε πεδία για κατάσταση φόρτωσης, δεδομένα και σφάλμα — όλα διαχειρίζονται μέσω AsyncSnapshot. Είναι ιδανικό για απλές οθόνες με μία ασύγχρονη λειτουργία (ένα αίτημα HTTP, ανάγνωση βάσης δεδομένων). Ωστόσο, με 5+ ασύγχρονες λειτουργίες σε μία οθόνη, το FutureBuilder δημιουργεί υπερβολική έμπνευση — σχηματίζεται μια «πυραμίδα» από έμπνευς FutureBuilder.

Το setState με μανυαλικά flags κατάστασης παρέχει περισσότερο έλεγχο και αναγνωσιμότητα σε σύνθετη λογική. Για οθόνες με πολλά εξαρτώμενα αιτήματα (φόρτωση χρήστη → φόρτωση παραγγελιών του → φόρτωση λεπτομερειών παραγγελίας) είναι καλύτερο να χρησιμοποιείτε 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) ή χρησιμοποιήστε memoization. Αν το Future δημιουργείται εντός της μεθόδου build, κάθε κλήση build θα δημιουργεί ένα νέο Future, και το FutureBuilder θα επανεκκινήσει την ασύγχρονη λειτουργία. Για StatelessWidget, χρησιμοποιήστε το πακέτο cached_future ή keep-alive widgets ώστε το 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 — widget 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. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.

Συζήτηση έργου

Διαβάστε επίσης