Flutter电商应用购物车计数器切换页面重置,如何实现数据持久化
解决方案
问题根因
你当前的计数器数值numOfItems是存储在CartCounter组件的本地State中的,当页面切换、组件销毁重建时,本地State会被重置,所以计数器会归零。而且你已经引入了Cart Provider做全局购物车管理,完全不需要在组件本地单独维护计数,直接从全局购物车读取对应商品的数量即可。
最优实现方案
你已经在使用Provider做状态管理,最优方案就是把计数器数据的来源绑定到全局Cart Provider,再给Cart加本地持久化存储,既不需要引入额外的状态管理库,也能保证APP重启后数据也不会丢失。
步骤1:改造CartCounter组件
移除本地维护的numOfItems状态,直接从Cart Provider中读取当前商品的购买数量,同时接收上层传递的product参数:
// cart_counter.dart import 'package:flutter/material.dart'; import '../providers/cart.dart'; import 'package:provider/provider.dart'; import '../providers/products.dart'; class CartCounter extends StatefulWidget { // 新增接收当前商品参数 final Product product; const CartCounter({Key? key, required this.product}) : super(key: key); @override _CartCounterState createState() => _CartCounterState(); } class _CartCounterState extends State<CartCounter> { // 移除本地的numOfItems变量 @override Widget build(BuildContext context) { // 这里listen设为true,购物车变化时自动刷新计数器 final cart = Provider.of<Cart>(context, listen: true); // 从购物车中获取当前商品的数量,不存在则返回0 int numOfItems = cart.items[widget.product.id]?.quantity ?? 0; return Row( mainAxisAlignment: MainAxisAlignment.center, children: [ CounterButton( icon: Icons.remove, onPress: () { if (numOfItems > 0) { cart.removeSingleItem(widget.product.id); } }, ), Padding( padding: const EdgeInsets.symmetric(horizontal: 13.0), child: Text( numOfItems.toString(), style: const TextStyle( fontSize: 20.0, ), ), ), CounterButton( icon: Icons.add, onPress: () { cart.addItem( widget.product.id, widget.product.price, widget.product.title, ); }, ), ], ); } } // CounterButton部分代码无修改,此处省略
步骤2:修改ProductItem传递product参数
你之前直接引用const CartCounter()没有传递当前商品数据,需要修改为传递当前产品:
// product_item.dart 对应位置修改 // 替换原来的 const CartCounter() CartCounter(product: Product(id, title, price, image)),
步骤3:给Cart Provider加本地持久化
推荐用Hive做本地存储,性能高、使用简单,不需要额外做JSON序列化:
- 先在pubspec.yaml引入hive和hive_flutter依赖
- 改造Cart类,在添加/删除商品的时候自动同步到本地Hive存储,APP启动时从Hive读取数据初始化购物车:
示例Cart类实现:
import 'package:flutter/foundation.dart'; import 'package:hive/hive.dart'; import '../models/cart_item.dart'; class Cart with ChangeNotifier { Map<String, CartItem> _items = {}; final Box _cartBox = Hive.box('cart'); Cart() { // 初始化时从本地读取购物车数据 var savedItems = _cartBox.get('items'); if (savedItems != null) { _items = Map<String, CartItem>.from(savedItems); } } Map<String, CartItem> get items => {..._items}; void addItem(String productId, double price, String title) { if (_items.containsKey(productId)) { _items.update(productId, (existing) => CartItem( id: existing.id, title: existing.title, price: existing.price, quantity: existing.quantity + 1, )); } else { _items.putIfAbsent(productId, () => CartItem( id: DateTime.now().toString(), title: title, price: price, quantity: 1, )); } // 同步到本地存储 _cartBox.put('items', _items); notifyListeners(); } void removeSingleItem(String productId) { if (!_items.containsKey(productId)) return; if (_items[productId]!.quantity > 1) { _items.update(productId, (existing) => CartItem( id: existing.id, title: existing.title, price: existing.price, quantity: existing.quantity - 1, )); } else { _items.remove(productId); } // 同步到本地存储 _cartBox.put('items', _items); notifyListeners(); } }
改造完成后,不管是切换页面还是重启APP,计数器的数值都不会丢失,完全和全局购物车数据同步。
内容的提问来源于stack exchange,提问作者supremo
相关产品推荐
相关产品推荐

