BLoC — τι είναι, Business Logic Component στο Flutter

Συγγραφέας: IT Sectr Δημοσιεύτηκε: 2026-02-19 Χρόνος ανάγνωσης: 7 λεπ

BLoC (Business Logic Component) — πρότυπο διαχείρισης κατάστασης για Flutter, που παρουσιάστηκε από την Google το 2018 στο DartConf. Το BLoC διαχωρίζει την επιχειρηματική λογική από τη διεπαφή χρήστη μέσω αντιδραστικών ροών (Stream): το UI στέλνει ένα Event, το BLoC το επεξεργάζεται και επιστρέφει μια νέα State μέσω Stream. Σύμφωνα με τα δεδομένα του pub.dev, το πακέτο flutter_bloc έχει συγκεντρώσει πάνω από 11 χιλιάδες likes και χρησιμοποιείται σε χιλιάδες εφαρμογές Flutter.

Κύρια σημεία

  • Event — σήμα εισόδου που περιγράφει την ενέργεια: πάτημα κουμπιού, φόρτωση δεδομένων
  • State — κατάσταση εξόδου του UI: δεδομένα φορτώθηκαν, σφάλμα, φόρτωση
  • Bloc — κύρια κλάση που δέχεται Event και επιστρέφει State μέσω Stream
  • Cubit — απλοποιημένη έκδοση του Bloc χωρίς Event, καλεί συναρτήσεις απευθείας
  • BlocProvider — widget Flutter για έγχυση του Bloc στο δέντρο widget

Τι είναι το BLoC;

BLoC (Business Logic Component) — αρχιτεκτονικό πρότυπο για Flutter στο οποίο η επιχειρηματική λογική βρίσκεται σε ξεχωριστή κλάση, απομονωμένη από το UI. Το BLoC λαμβάνει δεδομένα εισόδου μέσω μιας ροής συμβάντων (Event) και παράγει δεδομένα εξόδου μέσω μιας ροής καταστάσεων (State). Το επίπεδο παρουσίασης (Widget) απλώς εγγράφεται στη ροή State και εμφανίζει το UI, χωρίς ποτέ να εκτελεί επιχειρηματική λογική άμεσα.

Η ιδέα του BLoC βασίζεται στον αντιδραστικό προγραμματισμό και στο πρότυπο Observer. Κάθε στοιχείο BLoC είναι μια ξεχωριστή ενότητα με σαφή σύμβαση: το σύνολο Event (τι μπορεί να συμβεί) και το σύνολο State (τι μπορεί να εμφανιστεί) είναι γνωστά. Ο προγραμματιστής δεν μπορεί να αλλάξει "κατά λάθος" την κατάσταση από το UI — μόνο μέσω ενός συγκεκριμένου Event. Αυτό καθιστά τον κώδικα προβλέψιμο και ελέγξιμο.

Σύμφωνα με την έρευνα Flutter Community 2025, το BLoC καταλαμβάνει τη δεύτερη θέση σε δημοτικότητα μεταξύ των λύσεων διαχείρισης κατάστασης στο Flutter μετά το Provider. Κύρια πλεονεκτήματα: αυστηρή τυποποίηση, απομόνωση λογικής, ενσωματωμένη υποστήριξη Stream, πλούσιο οικοσύστημα βοηθητικών προγραμμάτων (BlocProvider, BlocListener, BlocSelector).

Αρχιτεκτονική BLoC: Event → Bloc → State

Αρχιτεκτονική BLoC χτίζεται γύρω από τρεις οντότητες: Event (είσοδος), Bloc (επεξεργαστής) και State (έξοδος). Το Widget στέλνει Event μέσω της μεθόδου add(). Το Bloc λαμβάνει το Event στη μέθοδο mapEventToState ή on<Event>, εκτελεί επιχειρηματική λογική και παράγει νέα State μέσω yield. Το Widget λαμβάνει State μέσω Stream και ανασχεδιάζεται.

Dart
abstract class CounterEvent {}

class Increment extends CounterEvent {}
class Decrement extends CounterEvent {}

class CounterBloc extends Bloc<CounterEvent, int> {
  CounterBloc() : super(0);

  @override
  Stream<int> mapEventToState(CounterEvent event) async* {
    if (event is Increment) {
      yield state + 1;
    } else if (event is Decrement) {
      yield state - 1;
    }
  }
}

Ασφάλεια τύπων: Το Bloc είναι παραμετροποιημένο με δύο τύπους — Event και State. Ο μεταγλωττιστής Dart ελέγχει ότι το Widget καλεί μόνο δηλωμένα Event και το Bloc επιστρέφει μόνο δηλωμένες State. Σφάλματα εκτέλεσης τύπου "Άγνωστη Ενέργεια" αποκλείονται.

Close και Dispose: Το Bloc υλοποιεί τη διεπαφή Closeable. Κατά την καταστροφή του widget, το Bloc κλείνει αυτόματα το Stream μέσω της μεθόδου close(). Διαρροές αντιδραστικών εγγραφών είναι αδύνατες — το BlocProvider διαχειρίζεται τον κύκλο ζωής του Bloc, συνδέοντάς το με μια διαδρομή ή σελίδα.

Bloc και Cubit: σύγκριση

Cubit — απλοποιημένη υλοποίηση του Bloc χωρίς Event, που παρουσιάστηκε στο πακέτο flutter_bloc 6.0. Το Cubit δηλώνει μεθόδους απευθείας αντί για κλάσεις Event: increment(), fetchData(). Εσωτερικά, το Cubit χρησιμοποιεί τον ίδιο μηχανισμό βασισμένο σε Stream, αλλά κρύβει το επίπεδο Event. Αυτό μειώνει τον boilerplate κατά 40-50% για απλά σενάρια.

ΧαρακτηριστικόBlocCubit
Κλάσεις EventΥποχρεωτικέςΔεν χρειάζονται
BoilerplateΥψηλόςΧαμηλός
Παρακολούθηση ενεργειώνΜέσω τύπου EventΜόνο όνομα μεθόδου
Κατάλληλο γιαΠολύπλοκα σενάριαΑπλές καταστάσεις
ΑναλυτικάΑυτόματα μέσω EventΧειροκίνητα

Πότε να επιλέξετε Cubit: κατάσταση με 2-3 παραλλαγές (loading, loaded, error), απλές φόρμες, μετρητές, καταστάσεις UI (ανοιχτό/κλειστό). Πότε Bloc: πολύπλοκη επιχειρηματική λογική με πολλαπλές ενέργειες: ολοκλήρωση παραγγελίας, έλεγχος ταυτότητας, συγχρονισμός δεδομένων. Το Bloc παρέχει λεπτομερή παρακολούθηση κάθε ενέργειας μέσω Event — κάθε κλήση καταγράφεται στο BlocObserver.

BlocObserver — καθολικός παρατηρητής που παρακολουθεί όλα τα Bloc και Cubit στην εφαρμογή. Επιτρέπει την καταγραφή Event, State, σφαλμάτων και μεταβάσεων. Αρκεί να συνδέσετε ένα αντίγραφο: Bloc.observer = AppBlocObserver(), και ολόκληρη η παρακολούθηση κατάστασης της εφαρμογής είναι διαθέσιμη συγκεντρωτικά.

BlocProvider και BlocBuilder

BlocProvider — InheritedWidget από το flutter_bloc που παρέχει το Bloc σε θυγατρικά widget. Κατά την αρχικοποίηση του widget, το BlocProvider δημιουργεί ένα Bloc, και κατά την καταστροφή — το κλείνει αυτόματα μέσω close(). Το BlocProvider μπορεί να τοποθετηθεί σε επίπεδο MaterialApp (καθολικό Bloc) ή σε επίπεδο συγκεκριμένης διαδρομής (τοπικό Bloc).

Dart
BlocProvider(
  create: (context) => CounterBloc(),
  child: Column(
    children: [
      BlocBuilder<CounterBloc, int>(
        builder: (context, state) => Text('$state'),
      ),
      ElevatedButton(
        onPressed: () => context.read<CounterBloc>().add(Increment()),
        child: Text('+'),
      ),
    ],
  ),
)

BlocBuilder — widget που αναδομεί το UI σε κάθε νέα State. BlocListener — για παρενέργειες (εφάπαξ επεξεργασία State χωρίς αναδόμηση UI): εμφάνιση SnackBar, πλοήγηση σε άλλη οθόνη. BlocConsumer — συνδυασμός Builder και Listener για περιπτώσεις όπου χρειάζεται τόσο αναδόμηση όσο και παρενέργεια. BlocSelector — για επιλεκτική αναδόμηση μόνο κατά την αλλαγή ενός συγκεκριμένου πεδίου της State.

MultiBlocProvider — widget για ένθετα BlocProvider χωρίς αύξηση του επιπέδου ένθεσης. Η εφαρμογή Flutter με 10-15 Bloc χρησιμοποιεί MultiBlocProvider στο ριζικό επίπεδο για την καταγραφή όλων των Bloc που είναι διαθέσιμα σε ολόκληρη την εφαρμογή: AuthenticationBloc, CartBloc, SettingsBloc.

Δοκιμή BLoC

Το BLoC δοκιμάζεται απομονωμένα χωρίς widget Flutter. Αρκεί να εισαγάγετε το πακέτο Dart flutter_test και το πακέτο bloc_test. Σενάριο δοκιμής: δημιουργήστε ένα Bloc, προσθέστε ένα Event, ελέγξτε τη State. blocTest — βοηθητικό πρόγραμμα που αυτοματοποιεί την ακολουθία: build → act → expect.

Dart
blocTest<CounterBloc, int>(
  'emits [1] when Increment is added',
  build: () => CounterBloc(),
  act: (bloc) => bloc.add(Increment()),
  expect: () => [1],
)

Mocking: Το BLoC που εξαρτάται από ένα repository ή API δοκιμάζεται με mock μέσω mocktail. Το Repository γίνεται mock σε επίπεδο αφαίρεσης, το Bloc λαμβάνει τις mock εξαρτήσεις μέσω κατασκευαστή. Hydrated Bloc — επέκταση για αυτόματη αποθήκευση/επαναφορά κατάστασης σε τοπική αποθήκευση. Δοκιμάζεται με HydratedBlocStorage και προσωρινή αποθήκευση αρχείων.

BLoC σε παραγωγή

Φάκελοι και αρχεία: τυπική δομή ενός έργου Flutter με BLoC: bloc/counter_bloc.dart, bloc/counter_event.dart, bloc/counter_state.dart. Για 30+ οθόνες, συνιστάται ομαδοποίηση ανά λειτουργία: features/auth/bloc/, features/cart/bloc/. Κάθε Bloc — ξεχωριστό αρχείο, κάθε Event και State — είτε σε ξεχωριστά αρχεία, είτε σε ένα αρχείο με το Bloc.

Απόδοση: Το BLoC δεν δημιουργεί επιβάρυνση σε κενά Stream. Το BlocBuilder χρησιμοποιεί buildWhen για φιλτράρισμα αναδομήσεων — το widget ενημερώνεται μόνο όταν αλλάξει μια συγκεκριμένη συνθήκη. Το Close εγγυάται ότι τα ανενεργά Bloc δεν καταναλώνουν μνήμη. Σύμφωνα με το Flutter DevTools, το BLoC προσθέτει λιγότερο από 1% στο μέγεθος του πακέτου.

Μετάβαση από Provider: Το BLoC συνυπάρχει εύκολα με το Provider στο ίδιο έργο. Σταδιακή μετάβαση: πρώτα αντικαθίστανται τα πιο πολύπλοκα Provider με Bloc, στη συνέχεια τα υπόλοιπα. Το BlocProvider είναι συμβατό με το δέντρο Provider: παλιά widget μπορούν να χρησιμοποιούν Provider, νέα — BlocProvider, στην ίδια εφαρμογή.

Συχνές Ερωτήσεις

Πώς διαφέρει το BLoC από το Provider στο Flutter;

BLoC χρησιμοποιεί Event + Stream για απομόνωση επιχειρηματικής λογικής και αυστηρή τυποποίηση. Provider — περιτύλιγμα γύρω από το InheritedWidget για απλή έγχυση εξαρτήσεων και ChangeNotifier. Το BLoC είναι καλύτερο για πολύπλοκα σενάρια με πολλαπλές καταστάσεις, το Provider — για τοπική κατάσταση UI. Το BLoC απαιτεί περισσότερο boilerplate, αλλά παρέχει πλήρη ιχνηλασιμότητα μέσω Event.

Τι είναι το Hydrated Bloc;

Hydrated Bloc — επέκταση από το πακέτο hydrated_bloc που αποθηκεύει αυτόματα την τελευταία State στην τοπική αποθήκευση (προεπιλογή Hive). Κατά την επανεκκίνηση της εφαρμογής, το Bloc επαναφέρει την αποθηκευμένη κατάσταση αντί για την αρχική. Αυτό λύνει το πρόβλημα της μονιμότητας χωρίς χειροκίνητη κλήση αποθήκευσης: σύνδεση, καλάθι, ρυθμίσεις αποθηκεύονται αυτόματα μεταξύ συνεδριών.

Πώς να χειριστείτε σφάλματα στο BLoC;

Το σφάλμα στο BLoC χειρίζεται μέσω try-catch μέσα στο mapEventToState ή on<Event>. Σε σφάλμα, το Bloc επιστρέφει State σφάλματος: yield LoadError(error.message). Στο UI, το BlocListener ή BlocConsumer ελέγχει τη State για τον τύπο σφάλματος και εμφανίζει SnackBar ή διάλογο. Το BlocObserver καταγράφει καθολικά όλες τις μη διαχειρισμένες εξαιρέσεις.

Μπορεί το BLoC να χρησιμοποιηθεί με άλλα frameworks;

Το BLoC είναι πρότυπο ειδικό για Flutter, καθώς χρησιμοποιεί Dart Stream και widget Flutter. Η ιδέα Event → Bloc → State μπορεί να προσαρμοστεί για AngularDart και Server-side Dart, αλλά το κύριο οικοσύστημα (BlocProvider, BlocBuilder, BlocObserver) συνδέεται με το Flutter. Για React Native χρησιμοποιήστε Redux ή MobX, για SwiftUI — Combine + MVVM.

Τι να επιλέξω: Bloc ή Cubit;

Cubit — για απλές καταστάσεις (μετρητής, toggle, φόρμα με 2-3 πεδία). Bloc — για πολύπλοκη λογική (ροή ειδήσεων, ολοκλήρωση παραγγελίας, έλεγχος ταυτότητας). Κύριος κανόνας: εάν απαιτείται παρακολούθηση κάθε ενέργειας (Event) για αναλυτικά ή εντοπισμό σφαλμάτων — Bloc. Εάν αρκούν μέθοδοι που αλλάζουν την κατάσταση — Cubit. Και τα δύο πρότυπα συνυπάρχουν στο ίδιο έργο.

Περίληψη

  • BLoC — πρότυπο διαχείρισης κατάστασης Flutter μέσω Event → Stream → State
  • Event — ενέργεια (κλικ, φόρτωση), State — αντίδραση (δεδομένα, σφάλμα, φόρτωση)
  • Cubit — απλοποιημένη έκδοση χωρίς Event, έως 50% λιγότερο boilerplate
  • BlocProvider — έγχυση Bloc στο δέντρο widget με αυτόματο close
  • BlocObserver — καθολική παρακολούθηση όλων των Bloc και Cubit στην εφαρμογή
  • Hydrated Bloc — αυτόματη μονιμότητα κατάστασης μέσω Hive
  • blocTest — βοηθητικό πρόγραμμα για αρθρωτή δοκιμή Bloc με απομόνωση από Flutter

Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση

Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.

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

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