Table of Contents
- Bloc stands for Business Logic Component
-
Bloc pattern consists of
- Event
- Bloc
- Stream
- Whereby an Event is triggered by a user action which gets dispatched to a bloc and emitted as a stream (sequence of async data) which can be used in a StreamBuilder or the UI is rebuild by the BlocBuilder each time the state changes
-
Each widget has its own Bloc which defines
- The initial state
- A reducer function which takes in the current state and event, and looks at the event itself to determine how to reduce the next state based on that event
- Simply, events are the input to a Bloc and states are the output of a Bloc; Events are dispatched and then converted to States
- Presentation components can listen to the stream of states and redraw themselves based on the given state (BlocBuilder)
- Good separation of concerns as the UI widgets are only concerned with rendering the UI and dispatching actions and does not contain or perform any business logic
Widgets | Description |
---|---|
BlocProvider | BlocProvider itself extends an InheritedWidget and provides a Bloc to its children, where they will be able to access the state and the data contained inside the Bloc |
BlocListener | BlocListener listens to the different states that would be emitted from Bloc and react to them (does not rebuild the UI) |
BlocBuilder | BlocBuilder takes the Bloc as an argument and accesses the current state inside of this function and rebuilds the UI each time the state changes |
- Define the different states Bloc will be emitting
- Define the different events Bloc will be reacting to
- Define Bloc’s initial state and functions which converts the incoming events into states that are consumed by the presentation layer
- Counter
- Infinite List
- Login
- Flutter 2.10.2
- Dart 2.16.1
- Xcode 13.2.1
Run flutter doctor
in the terminal to check if you are using the same versions
$ flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 2.10.2, on macOS 11.6.5 20G527 darwin-x64, locale
en-SG)
[✓] Android toolchain - develop for Android devices (Android SDK version 31.0.0)
[✓] Xcode - develop for iOS and macOS (Xcode 13.2.1)
[✓] Chrome - develop for the web
[✓] Android Studio (version 2020.3)
[✓] VS Code (version 1.66.2)
[✓] Connected device (1 available)
[✓] HTTP Host Availability
• No issues found!
From the root of the project, run flutter pub get
to retrieve the dependencies
$ flutter pub get
Run open -a simulator
to launch the ios emulator
$ open -a simulator
Run flutter run
to start the project
$ flutter run
- BlocObserver
- Cubit vs Bloc
Cubit | Bloc |
---|---|
When creating a Cubit, we have to define the state and the functions to trigger state changes | When creating a Bloc, we have to define the state, event and event handler |
Simpler as less code is involved | More traceable as we know the event that triggered those changes |
-
CounterCubit
- Does not specify the event that triggers the function for the state to change, rather it only exposes the function to emit the new changes
- Can be good if only one event is responsible for a widget to redraw and state change does not require complex logic
-
CounterView
- Button press does not dispatch an event to the intermediary to decide how to change the state but rather it calls the CounterCubit methods straight which immediately accesses and outputs the new state
-
BlocObserver
- Responds to all changes even if there are more than one Cubit across the App managing different states, such as handling all reported errors globally
- Created at the root widget
- Equatable
- Adding events
- Defining states
- Transition
-
PostBloc
- Responds to PostFetched, which is a type of PostEvent, using an event handler
- Emits the PostStates which tells the presentation layer what to do
- PostEvent and PostState extends Equatable so that we can directly compare states and not rebuild the widget if the same state occurs; objects with the same value have different hashcode internally
-
PostsPage
- Contains an instance of PostBloc that adds PostFetched event which triggers on creation and renders PostsList
-
PostsList
- Uses a BlocBuilder to rebuild the view depending on the state, and is hooked up to PostBloc and adds a PostFetched event when it reaches the bottom of the scroll
- Instead of using switch case, can also try using buildWhen() which rebuilds the view when the current state is PostStatus.success
-
BlocObserver
- onTransition can be used in BlocObserver to log the changes in state
- Stream
- RepositoryProvider
-
UserRepository
- Exposes a method getUser() which will retrieve the current user
- Wrapped with RepositoryProvider to provide a repository for all the Blocs
-
AuthenticationRepository
- Exposes a stream of AuthenticationStatus updates
- Report real-time updates to all subscribers
- Wrapped with RepositoryProvider to provide a repository for all the Blocs
-
AuthenticationBloc
- Reacts to changes in the authentication state and emit states to the presentation layer
- Has a dependency on AuthenticationRepository and UserRepository and subscribes to the status stream of the AuthenticationRepository and adds AuthenticationStatusChanged event internally in response to a new AuthenticationStatus
-
LoginBloc
- Login state and events are decoupled from Authentication
-
Presentation Layer
- Splash page: splash screen while bloc determines whether user is logged in
- Home page: navigates users there once they are logged in
- Login page: holds Login form
- Login form: handle user login input
-
MultiBlocProvider
- Can be used to initialize all the Blocs