'How To Listen to BLoC Events From Another Screen in Flutter

SOLVED: I WAS GETTING ANOTHER STATE INSTEAD OF WHAT I EXPECTED

I have two screens in my app. The first one contains products and each one of them is wrapped with a CheckboxListTile the checkbox value is a variable that's it's value is specified by checking if the product's id exist in a list called selectedItemsList, now the second screen is a cart screen that holds the selected products from the first screen, each cartItem is wrapped in a Dismissible, the onDismissed function removes the product from the cart and removes it's id from the selectedItemsList list.

What I want is to change the checkbox value after it has been removed from the cart when I press the back button and navigate back to the products screen from the cart screen.

My goal in a more explained way:

  1. Products screen has 2 products (p1 and p2).
  2. I select p1 and it's added to the cart and it's id is added to the selectedItemsList.
  3. The value of the p1 checkbox is true (checked).
  4. I navigate to cart screen and I remove the p1 from there.
  5. p1 is now removed from cart and it's id is removed from selectedItemsList.
  6. I press the back button and navigate back to products screen.
  7. The p1 checkbox value should be false (not checked) because it's id is not in the selectedItemsList, but it's still true (checked).
  8. I want to update (or actually rebuild) the products screen when I remove a product from cart in the cart screen.

I'm implementing the things mentioned above using he bloc pattern. I'm firing an event called RemoveItemFromCart from a CartBloc:

void _onDismissed({
    required BuildContext context,
    required int index,
  }) {
    BlocProvider.of<CartBloc>(context).add(
      RemoveItemFromCart(
        items: _cartItems,
        index: index,
        counts: _counts,
        filteredCounts: _filteredCounts,
        originalIndices: _originalIndices,
        filteredItems: _filteredCartItems,
        filtering: _filtering,
      ),
    );

    _firstTime = true;
  }

Then a state called ItemRemovedFromCart is yielded:

if (event is RemoveItemFromCart) {
      if (event.filtering &&
          event.originalIndices.isNotEmpty &&
          event.filteredCounts.isNotEmpty &&
          event.filteredItems.isNotEmpty) {
        int itemIndex = event.items.indexWhere(
          (item) => item.id == event.filteredItems[event.index].id,
        );
        productsRepository.unSelectProduct(
          id: event.items[itemIndex].id,
        );
        event.items.removeAt(itemIndex);
        event.counts.removeAt(itemIndex);
        event.filteredItems.removeAt(event.index);
        event.filteredCounts.removeAt(event.index);
        event.originalIndices.removeAt(event.index);
      } else {
        productsRepository.unSelectProduct(
          id: event.items[event.index].id,
        );
        event.items.removeAt(event.index);
        event.counts.removeAt(event.index);
      }

      yield ItemRemovedFromCart(
        items: event.items,
        counts: event.counts,
        filteredCounts: event.filteredCounts,
        filteredItems: event.filteredItems,
        originalIndices: event.originalIndices,
      );
    }

In the products screen I'm using a BlocBuilder to rebuild when this state is yielded (but for now I'm just trying to print a test string to see if it's working):

BlocBuilder<CartBloc, CartState>(
  builder: (context, state) {
   if (state is ItemRemovedFromCart) print('asd');
   return _buildProductsList(products, context);
  },
)

The print statement is not being executed, so how to listen to events from another screen?

Thanks in advance.



Solution 1:[1]

I figured out that bloc instances keep listening to events as long as they are not closed or disposed, so if we want to act upon events from another screen we simply add an event to the required bloc and that's it

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Bakri Alkhateeb