We will go over the three questions to start using the Bloc, —
1. How to make Bloc available to the Widget tree (UI)?
The Widget which gives this functionality is the BlocProvider widget, BlocProvider makes the bloc available to the entire Widget tree, which is passed in the
In the above code, we create a new instance of the
LoginBlocand as a child, we pass the instance of our
LoginScreen so Bloc Provider makes the
LoginBloc available to the Widget tree of
LoginScreen Bloc Provider automatically handles the closing of the Bloc.
2. How to trigger an Event from UI on some action?
Now that we have Bloc available on the Widget tree we can access it from anywhere, there are two ways to do that, —
a. Using context,
b. Using Bloc Provider,
But what is the difference? When should we use which one?
There is actually not much difference both are almost the same, but the first one is defined as an extension on the
BuildContext, so it’s easier to use. Proceed with whichever you like.
Let’s add a button tap event on the Bloc, —
Note: — It’s important to pass the correct type of the Bloc, because it tries to lookup the tree to find the instance of that type, you can read more on this here.
Coming back to the event, see how easy its to trigger an event from UI, we just call the
addmethod on the Bloc, and pass an instance of an event.
Now we need to go back to the Bloc and check if we have registered this event which is sent from the UI, on receiving this we will emit a State with a String to show on the UI, you can refer to the Bloc code attached above , just uncomment all the code with the comment “will be used later”. Great that’s it.
3. But how will UI update itself when a new state is Emitted?
Yes, you guessed that right, there is a widget for this too. It’s called Bloc Consumer.
Let’s go over the
BlocConsumerthough the above example contains the entire
LoginScreen but for now, you need to focus only on
If you notice the
BlocConsumer have four arguments let’s go over them one by one,
builder — It rebuilds the widget tree in response to the state changes, which means whenever you emit a new state it will rebuild the widgets so that you can use the value sent in the state that is emitted from the Bloc. So in this example, we have passed a text from the bloc in the
UpdateTextStateand used it to so on the UI, this state is emitted whenever the “Tap me!!” button is tapped.
listener — So whenever a state is emitted the listener also gets invoked, but unlike builder, it doesn’t return any widget. It gets called once per state change, that’s why we generally use a listener that happens once whenever the state changes, like showing a snack bar, dialog, bottom sheet, or navigating to the next screen.
buildWhen — This is an optional parameter that provides previous and current states and returns a boolean, so if we return true it will call the builder, or else it won’t if you don’t use this parameter the builder will be called for each state change.
listenWhen — This is similar to
buildWhen but used to control the Listener, if it returns true then the listener gets called.
So in our example, we are using Listener for
ShowSnackBar state, which shows a snack bar with a text to display when the button is tapped. and we are using builder for
UpdateTextState which updates the text on the screen when a button is tapped.
Another interesting point to note is that
BlocConsumer takes in an optional parameter bloc, if you don’t provide it, it will try to lookup using
BlocProvider and the current
BuildContext . So if you missed injecting the Bloc (Question 1) it will throw an exception.
There will be cases where you either want to use
listener for such cases there are different
BlocListener widgets, feel free to explore them, also Flutter blocs provide some other helpful widgets but that’s for some other day.