Flutter购物车无法显示Firestore商品及总价计算异常问题求助
Hey there! Let's tackle your two Flutter e-commerce issues one by one, with fixes tailored to your code:
Issue 1: Firestore Products Not Showing in Cart Page
Looking at your StreamBuilder code, here are the likely culprits and fixes:
1.1 Invalid userCartList Initialization
Your checkout button checks if userCartList.length == 1 to show an empty cart message—this suggests your cart list is initialized with an empty string ([""]) instead of an empty array ([]). When Firestore runs the whereIn query with this list, it looks for items with an empty shortInfo (which don't exist), leading to no results.
Fix: Update your shared preferences initialization to set an empty list by default:
// Run this once when your app starts (e.g., in main.dart or auth screen) if (!EcommerceApp.sharedPreferences.containsKey(EcommerceApp.userCartList)) { EcommerceApp.sharedPreferences.setStringList(EcommerceApp.userCartList, []); }
Then adjust your checkout button's empty cart check to use isEmpty:
if (EcommerceApp.sharedPreferences.getStringList(EcommerceApp.userCartList)?.isEmpty ?? true) { Fluttertoast.showToast(msg: "Your Cart is empty!"); }
1.2 Filter Invalid IDs in whereIn Query
Even if you fix initialization, there might be stray empty IDs in the cart list. Add a filter to remove empty strings before passing to Firestore:
stream: EcommerceApp.firestore.collection("/items") .where("shortInfo", whereIn: EcommerceApp.sharedPreferences.getStringList(EcommerceApp.userCartList)? .where((id) => id.isNotEmpty) .toList() ?? [] ).snapshots(),
1.3 Improve StreamBuilder Loading State Handling
Your current code only checks !snapshots.hasData for loading, but you should explicitly handle the connection state to avoid glitches:
builder: (context, snapshots) { // Show loading spinner while fetching data if (snapshots.connectionState == ConnectionState.waiting) { return SliverToBoxAdapter(child: Center(child: circularProgress()),); } // Show empty cart if no valid items exist if (!snapshots.hasData || snapshots.data!.docs.isEmpty) { return beginBuildinCart(); } // Proceed to build cart items // ... rest of your code }
Issue 2: Total Price Calculation Not Working
Your current approach of calculating total amount inside the SliverChildBuilderDelegate is unreliable because list items can be rebuilt/reused by Flutter, leading to incorrect or duplicate calculations. Here's a better approach:
2.1 Calculate Total Price Before Building List Items
Compute the total once you have the Firestore data, outside the item builder, to ensure accuracy:
StreamBuilder<QuerySnapshot>( stream: // ... your corrected stream, builder: (context, snapshots) { // ... loading and empty state checks from Issue 1 ... // Calculate total price once for all items double calculatedTotal = 0.0; final cartItems = snapshots.data!.docs; for (var doc in cartItems) { ItemModel model = ItemModel.fromJson(doc.data() as Map<String, dynamic>); calculatedTotal += model.price; } // Update TotalAmount provider after the widget frame is built WidgetsBinding.instance.addPostFrameCallback((_) { Provider.of<TotalAmount>(context, listen: false).display(calculatedTotal); }); // Build the cart items list return SliverList( delegate: SliverChildBuilderDelegate( (context, index) { ItemModel model = ItemModel.fromJson(cartItems[index].data() as Map<String, dynamic>); return sourceInfo( model, context, removeCartFunction: () => removeItemFromUserCart(model.shortInfo) ); }, childCount: cartItems.length ), ); }, )
2.2 Verify TotalAmount Provider Implementation
Make sure your TotalAmount class correctly notifies listeners when updating the total:
class TotalAmount extends ChangeNotifier { double _totalAmount = 0.0; double get totalAmount => _totalAmount; void display(double newAmount) { _totalAmount = newAmount; notifyListeners(); // Critical to update UI } }
2.3 Fix removeItemFromUserCart to Update State
Ensure removing an item updates both shared preferences and the CartItemCounter provider (to refresh the total price and cart item count):
void removeItemFromUserCart(String shortInfoAsId) { List<String> updatedCart = EcommerceApp.sharedPreferences.getStringList(EcommerceApp.userCartList)!; updatedCart.remove(shortInfoAsId); // Save updated cart to shared preferences EcommerceApp.sharedPreferences.setStringList(EcommerceApp.userCartList, updatedCart); // Update cart item count provider Provider.of<CartItemCounter>(context, listen: false).displayResult(updatedCart.length); }
These changes should resolve both the missing cart items and incorrect total price issues. Let me know if you run into any edge cases!
内容的提问来源于stack exchange,提问作者Mohamed Keke

