My bloc is yielding new states e.g. like this:
yield Loaded();
yield Loaded();
My BlocListener retrieves both of these, even though they are the same.
My BlocBuilder on the other hand does not. It will only retrieve the first (or last?) one.
I'm not using equatable and I don't understand why BlocBuilder wont be triggered both times.
In my case I simply want to update the UI again without actually changing the state.
Building widgets is an expensive task and Flutter tries to minimize this cost wherever possible. One of them is preventing repetitive building when state changes. Here is an example:
class TestPage extends StatefulWidget {
@override
_TestPageState createState() => _TestPageState();
}
class _TestPageState extends State<TestPage> {
int a = 0;
@override
Widget build(BuildContext context) {
print(a);
return Scaffold(
floatingActionButton: FloatingActionButton(onPressed: () {
setState(() => a = 1);
setState(() => a = 1);
}),
);
}
}
This example prints 0 at the first build. After clicking on the button you should expect 2 prints with value of 1 but you will get only one message in the console. Because setState
does not immediately cause a rebuild. setState
will immediately call the closure passed to it and then marks your widget as dirty (to get rebuild in the next frame). That's why calling setState
multiple times fires build
method of your widget only once. Now if you change the last setState
in that code to setState(() => a = 2)
you will get 2 in the console after clicking on button. If you reverse them (set a to be 2 at first and then 1) you will get 1 in the console. Now with that in mind let's see how BlocBuilder
works?
BlocBuilder
is a StatefulWidget
and uses BlocListener
to update it's state and rebuild the widgets if needed. Here is it's build
method:
@override
Widget build(BuildContext context) {
return BlocListener<C, S>(
cubit: _cubit,
listenWhen: widget.buildWhen,
listener: (context, state) => setState(() => _state = state),
child: widget.build(context, _state),
);
}
As you can see the same behavior we saw in our example applies here too and if you yield multiple states repetitively in a short time, It will get built once with the latest state.