I'm building a tic-tak-toe app and I decided to learn BLoC for Flutter along. I hava a problem with the BlocBuilder widget.
As I think about it. Every time Cubit/Bloc that the bloc builder widget listens to emits new state the bloc builder goes through this routine:
Call
buildWhencallback passing previous state as thepreviousparameter and the newly emitted state as thecurrentparameter.If the
buildWhencallback returned true then rebuild.During rebuilding call the
buildercallback passing given context ascontextparameter and the newly emitted state asstateparameter. This callback returns the widget that we return.
So the conclusion is that the current parameter of the buildWhen call is always equal to the state parameter of the builder call. But in practice it's different:
BlocBuilder<GameCubit, GameState>(
buildWhen: (previous, current) => current is SetSlotSignGameState && (current as SetSlotSignGameState).slotPosition == widget.pos,
builder: (context, state) {
var sign = (state as SetSlotSignGameState).sign;
// Widget creation goes here...
},
);
In the builder callback, it throws:
The following _CastError was thrown building BlocBuilder<GameCubit, GameState>(dirty, state: _BlocBuilderBaseState<GameCubit, GameState>#dc100): type 'GameState' is not a subtype of type 'SetSlotSignGameState' in type cast The relevant error-causing widget was: BlocBuilder<GameCubit, GameState>
The method where I emit the states that is in the GameCubit class:
// [pos] is the position of the slot clicked
void setSlotSign(Vec2<int> pos) {
// Some code
emit(SetSlotSignGameState(/* Parameter representing the sign that is being placed in the slot*/, pos));
// Some code
emit(TurnChangeGameState());
}
Briefly about types of states. SetSlotSignGameState is emitted when a user taps on a slot in the tic-tac-toe grid and the slot is empty. So this state means that we need to change sign in some slot. TurnChangeGameState is emitted when we need to give the turn to the next player.
Temporary solution. For now I fixed it by saving the state from buildWhen callback in a private field of the widget's state and then using it from the builder. BlocListener also has this problem but there I can just move the check from listenWhen callback into listen callback. The disadvantage of this solution is that it's very inelegant and inconvenient.