'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:
- Products screen has 2 products (p1 and p2).
- I select p1 and it's added to the cart and it's id is added to the
selectedItemsList
. - The value of the p1 checkbox is true (checked).
- I navigate to cart screen and I remove the p1 from there.
- p1 is now removed from cart and it's id is removed from
selectedItemsList
. - I press the back button and navigate back to products screen.
- The p1 checkbox value should be false (not checked) because it's id is not in the
selectedItemsList
, but it's still true (checked). - 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 |