Search code examples
flutterbloc

Flutter: BlocSelector not emitting updates


So I have 2 views('View Items','History)'. I move the items from 'View Item's -> 'History' when the time attached to each of the object runs out.

The thing is, my 'View Items' view is updated with each state change (and items do move automatically from 'View Items' -> 'History' by themselves). However, when I'm inside my 'History' view and wait for items to move into it, they don't move into it.

I'm using a BlocSelector, and "subscribing" to changes of some collection inside my state. Here's my Bloc state:

class BlocState {
  const BlocState(this.objectsHistory = const <SomeObject>[]);

  final List<SomeObject> objectsHistory; // the items I want to display inside my 'History' view
}

And here's my widget:

  @override
  Widget build(BuildContext context) {
    return BlocSelector<MyBloc, Bloctate, List<MyObject>>(
        selector: (state) => state.objectsHistory,
        builder: (context, objectsHistory) {
          print(objectsHistory.length); // this will not emit a new value when a new state is emitted (unlike 'View Items' view which has a similar build method which does)
          return const Text('data');
        },
      ),
  }

Note: When I simply use a BlocBuilder and emit every state change, the data is updated automatically (inside 'History' view)

Am I doing this wrong?


Solution

  • The issue is that objectsHistory is a list and modifying it won't create another list. it's still the same list instance, and I assume when you emit a new state inside your bloc, you give the same objectsHistory instance to the emitted state. Because BlocSelector checks the equality of the two last selected values. they are the same, hence no rebuild will happen.

    I assume if you create a new list every time you emit a new state, it will rebuild.

    Like when you emit the new state and pass the modified instance objectsHistory you use toList to create another list from the current list:

    emit(BlocState(objectHistory.toList()));