Dart/Flutter中如何在清空购物车数据前保留其内容到订单?
订单历史页面数据保留问题解决
数据结构说明
<Map<String, dynamic>> instrument:单个乐器的映射对象List<Map<String, dynamic>> instruments:乐器列表List<Map<String, dynamic>> cartList:加入购物车的乐器列表Map<Map<String, dynamic>, int> cartMap:映射购物车中每个乐器的选购数量List<List<Map<String, dynamic>>> ordersList:订单列表Map<List<Map<String, dynamic>>, DateTime> ordersDate:映射每个订单的创建时间List<Map<Map<String, dynamic>, int>> ordersMap:映射每个订单中乐器的选购数量
支付按钮原逻辑代码
ElevatedButton( onPressed: () { ordersList.add(cartList.toList()); ordersDate.addAll({cartList.toList(): DateTime.now()}); ordersMap.add(cartMap); cartList.clear(); cartMap.clear(); Navigator.pushNamed(context, "/orders-history"); }, )
订单历史页面原展示代码
SizedBox( width: screenWidth * 0.95, height: screenHeight * 0.8, child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ Expanded( child: ListView.builder( itemCount: ordersList.length, itemBuilder: (BuildContext context, int index) { return SizedBox( width: screenWidth * 0.95, height: screenHeight * 0.10 * ordersList[index].length, child: Column( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.start, children: [ Text("${ordersDate[ordersList[index]]}"), Expanded( child: ListView.builder( itemCount: ordersList[index].length, itemBuilder: (BuildContext context, int index2) { return ListTile( leading: Image( image: NetworkImage(ordersList[index] [index2]["img-url"])), title: Text( ordersList[index][index2]["name"]), subtitle: Text( "${ordersMap[index][ordersList[index][index2]].toString()} units"), trailing: Text( "₹${ordersList[index][index2]["price"].toString()}"), ); }), ), ], ), ); }, ), ), ], ), )
问题分析
订单历史页面中ordersDate[ordersList[index]]和ordersMap[index][ordersList[index][index2]]显示为null,核心原因是引用传递导致的数据丢失:
- 两次调用
cartList.toList()会生成两个独立的列表引用,ordersList中存储的列表和ordersDate的key不是同一个引用,后续查找时因引用不匹配返回null。 ordersMap.add(cartMap)添加的是原购物车Map的引用,执行cartMap.clear()后,原Map内容被清空,ordersMap中对应的元素也会变成空Map,导致数量查询为null。
解决方案
1. 修复现有结构的支付逻辑
统一创建购物车数据的独立副本,确保引用一致且不受后续清空操作影响:
onPressed: () { // 深拷贝购物车列表(每个乐器Map也复制一份,避免后续修改影响历史数据) final orderItems = cartList.map((instrument) => Map<String, dynamic>.from(instrument)).toList(); // 创建购物车数量Map的独立副本 final orderQtyMap = Map<Map<String, dynamic>, int>.from(cartMap); // 使用统一的副本添加到订单数据中 ordersList.add(orderItems); ordersDate[orderItems] = DateTime.now(); ordersMap.add(orderQtyMap); // 清空购物车 cartList.clear(); cartMap.clear(); Navigator.pushNamed(context, "/orders-history"); },
2. 优化数据结构(更可靠的长期方案)
用乐器的唯一ID(比如每个instrument对象中的"id"字段)替代整个Map作为cartMap的key,避免Map引用相等性带来的问题:
- 修改数据结构:
Map<String, int> cartMap:key为乐器ID,value为选购数量List<Map<String, int>> ordersMap:每个订单的ID-数量映射
- 支付按钮逻辑修改:
onPressed: () { final orderItems = cartList.map((item) => Map<String, dynamic>.from(item)).toList(); final orderQtyMap = Map<String, int>.from(cartMap); ordersList.add(orderItems); ordersDate[orderItems] = DateTime.now(); ordersMap.add(orderQtyMap); cartList.clear(); cartMap.clear(); Navigator.pushNamed(context, "/orders-history"); },
- 订单历史页面数量查询代码修改:
subtitle: Text( "${ordersMap[index][ordersList[index][index2]["id"]].toString()} units"),
这种方案更稳定,字符串ID的相等性判断基于内容而非引用,不会因对象引用变化导致查询失败。
内容的提问来源于stack exchange,提问作者Ayan Dasgupta
相关产品推荐
相关产品推荐

