Flutter电商APP购物车会话管理问题(基于SharedPreference)
1. 定义可序列化的购物车商品模型
SharedPreference仅支持存储基础类型,因此需要将商品数据序列化为JSON字符串。创建CartItem类并实现序列化/反序列化方法:
class CartItem { final String id; final String name; final double price; final int quantity; CartItem({ required this.id, required this.name, required this.price, required this.quantity, }); // 转JSON对象 Map<String, dynamic> toJson() => { 'id': id, 'name': name, 'price': price, 'quantity': quantity, }; // 从JSON转对象 factory CartItem.fromJson(Map<String, dynamic> json) => CartItem( id: json['id'], name: json['name'], price: json['price'], quantity: json['quantity'], ); }
2. 创建全局购物车管理单例
用单例类统一处理购物车的增删改查及SharedPreference读写,确保全项目数据同步:
import 'dart:convert'; import 'package:shared_preferences/shared_preferences.dart'; class CartManager { static final CartManager _instance = CartManager._internal(); factory CartManager() => _instance; CartManager._internal(); List<CartItem> _cartItems = []; final String _storageKey = 'app_cart_items'; // 初始化:从SharedPreference加载历史数据 Future<void> init() async { final prefs = await SharedPreferences.getInstance(); final String? cartJson = prefs.getString(_storageKey); if (cartJson != null) { List<dynamic> jsonList = jsonDecode(cartJson); _cartItems = jsonList.map((item) => CartItem.fromJson(item)).toList(); } } // 获取只读购物车列表 List<CartItem> get cartItems => List.unmodifiable(_cartItems); // 添加商品(已存在则累加数量) Future<void> addItem(CartItem item) async { final existingIndex = _cartItems.indexWhere((cartItem) => cartItem.id == item.id); if (existingIndex != -1) { _cartItems[existingIndex] = CartItem( id: item.id, name: item.name, price: item.price, quantity: _cartItems[existingIndex].quantity + item.quantity, ); } else { _cartItems.add(item); } await _saveToStorage(); } // 更新商品数量(数量≤0则删除) Future<void> updateQuantity(String itemId, int newQuantity) async { final index = _cartItems.indexWhere((item) => item.id == itemId); if (index != -1 && newQuantity > 0) { _cartItems[index] = CartItem( id: _cartItems[index].id, name: _cartItems[index].name, price: _cartItems[index].price, quantity: newQuantity, ); await _saveToStorage(); } else if (newQuantity <= 0) { await removeItem(itemId); } } // 删除商品 Future<void> removeItem(String itemId) async { _cartItems.removeWhere((item) => item.id == itemId); await _saveToStorage(); } // 清空购物车 Future<void> clearCart() async { _cartItems.clear(); await _saveToStorage(); } // 私有方法:将购物车数据持久化到SharedPreference Future<void> _saveToStorage() async { final prefs = await SharedPreferences.getInstance(); List<Map<String, dynamic>> jsonList = _cartItems.map((item) => item.toJson()).toList(); await prefs.setString(_storageKey, jsonEncode(jsonList)); } }
3. 启动APP时初始化购物车
在main函数中提前加载历史购物车数据,确保APP启动后数据可用:
import 'package:flutter/material.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); await CartManager().init(); runApp(const MyApp()); }
4. 各页面集成购物车功能
商品页添加商品
// 商品页添加按钮点击事件 onPressed: () async { final newCartItem = CartItem( id: 'prod_001', name: '示例商品', price: 99.9, quantity: 1, ); await CartManager().addItem(newCartItem); // 可添加弹窗提示或直接跳转购物车页 },
购物车页展示商品
结合ChangeNotifier实现数据实时刷新(需修改CartManager继承ChangeNotifier,并在数据变更时调用notifyListeners()):
// 修改CartManager继承ChangeNotifier class CartManager extends ChangeNotifier { // ... 原有代码 ... Future<void> addItem(CartItem item) async { // ... 原有逻辑 ... await _saveToStorage(); notifyListeners(); // 通知页面刷新 } // updateQuantity、removeItem、clearCart方法均需添加notifyListeners() } // 购物车页面代码 class CartPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('购物车')), body: Consumer<CartManager>( builder: (context, cartManager, child) { if (cartManager.cartItems.isEmpty) { return const Center(child: Text('购物车为空')); } return ListView.builder( itemCount: cartManager.cartItems.length, itemBuilder: (context, index) { final item = cartManager.cartItems[index]; return ListTile( title: Text(item.name), subtitle: Text('¥${item.price} x ${item.quantity}'), trailing: Row( mainAxisSize: MainAxisSize.min, children: [ IconButton( icon: const Icon(Icons.remove), onPressed: () => cartManager.updateQuantity(item.id, item.quantity - 1), ), Text('${item.quantity}'), IconButton( icon: const Icon(Icons.add), onPressed: () => cartManager.updateQuantity(item.id, item.quantity + 1), ), ], ), ); }, ); }, ), ); } }
首页展示购物车入口及数量
在首页AppBar添加购物车图标,并实时显示商品数量:
AppBar( title: const Text('首页'), actions: [ Stack( children: [ IconButton( icon: const Icon(Icons.shopping_cart), onPressed: () { Navigator.push(context, MaterialPageRoute(builder: (_) => CartPage())); }, ), Positioned( right: 8, top: 8, child: Container( padding: const EdgeInsets.all(2), decoration: BoxDecoration( color: Colors.red, borderRadius: BorderRadius.circular(10), ), constraints: const BoxConstraints(minWidth: 16, minHeight: 16), child: Consumer<CartManager>( builder: (context, cartManager, child) { return Text( '${cartManager.cartItems.length}', style: const TextStyle(color: Colors.white, fontSize: 12), textAlign: TextAlign.center, ); }, ), ), ), ], ), ], )
核心优势
- 单例模式确保全项目使用同一购物车数据源,避免页面跳转数据不一致
- SharedPreference持久化存储,APP重启后购物车数据不会丢失
- 结合
ChangeNotifier实现页面数据实时刷新,无需手动重载页面
内容的提问来源于stack exchange,提问作者Dhaneshwar Shruti
相关产品推荐
相关产品推荐

