Flutter中List<Model>数据统计:POS应用总价计算问题
POS应用总价计算问题
问题场景
开发POS(销售点)应用时,待购买商品列表的数量加减按钮点击后,对应商品的总价无法实时更新到界面上。
现有代码
1. 向列表添加数据的代码
final List<Product> listProduct; widget.listProduct.add(data);
2. Product模型
Product productFromJson(String str) => Product.fromJson(json.decode(str)); String productToJson(Product data) => json.encode(data.toJson()); class Product { final int id; final int categoryId; final String productName; final int productQuantity; final int productCost; final int productPrice; final String image; int quantity = 1; int total = 0; final DateTime createdAt; final DateTime updatedAt; Product({ required this.id, required this.categoryId, required this.productName, required this.productQuantity, required this.productCost, required this.productPrice, required this.image, required this.createdAt, required this.updatedAt, }); factory Product.fromJson(Map<String, dynamic> json) => Product( id: json["id"], categoryId: json["category_id"], productName: json["product_name"], productQuantity: json["product_quantity"], productCost: json["product_cost"], productPrice: json["product_price"], image: json['image'], createdAt: DateTime.parse(json["created_at"]), updatedAt: DateTime.parse(json["updated_at"]), ); Map<String, dynamic> toJson() => { "id": id, "category_id": categoryId, "product_name": productName, "product_quantity": productQuantity, "product_cost": productCost, "product_price": productPrice, "created_at": createdAt.toIso8601String(), "updated_at": updatedAt.toIso8601String(), }; }
3. DataTable展示代码
DataTable( columns: const <DataColumn>[ DataColumn(label: Text('No',style: TextStyle(fontStyle: FontStyle.italic))), DataColumn(label: Text('Product Name',style: TextStyle(fontStyle: FontStyle.italic),),), DataColumn(label: Text('Price',style: TextStyle(fontStyle: FontStyle.italic),),), DataColumn(label: Text('Amount',style: TextStyle(fontStyle: FontStyle.italic),),), DataColumn(label: Text('Total',style: TextStyle(fontStyle: FontStyle.italic),),), DataColumn(label: Text('Delete',style: TextStyle(fontStyle: FontStyle.italic),),), ], rows: List.generate(widget.listProduct.length, (index) { Product dataProduct = widget.listProduct[index]; int total = dataProduct.quantity * dataProduct.productPrice; String totalHarga = total.toString(); return DataRow( cells: <DataCell>[ DataCell(Text('${index + 1}.')), DataCell(Text(dataProduct.productName)), DataCell(Text(dataProduct.productPrice.toString())), DataCell(Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ IconButton( onPressed: () { setState(() { if (dataProduct.quantity >= 2) { dataProduct.quantity--; total = dataProduct.quantity * dataProduct.productPrice; } else { return; } }); }, icon: Icon(Icons.remove)), Text(dataProduct.quantity.toString()), IconButton( onPressed: () { setState(() { dataProduct.quantity++; total = dataProduct.quantity * dataProduct.productPrice; print(total); }); }, icon: Icon(Icons.add)), ], )), DataCell(Text(totalHarga)), DataCell( Icon(Icons.delete), onTap: () { widget.listProduct.remove(dataProduct); getProductData(); }, ) ], ); } ), ),
问题原因
totalHarga是在List.generate初始化时计算的固定字符串,点击加减按钮后,局部变量total的更新无法同步到界面显示的totalHarga。- 直接修改
Product类的quantity字段,即使调用setState,Flutter也无法检测到普通对象内部字段的变化,导致界面未正确重建。
解决方案
1. 直接在界面渲染时计算总价
修改总价对应的DataCell,每次界面重建时基于最新的quantity计算总价:
DataCell(Text((dataProduct.quantity * dataProduct.productPrice).toString())),
删除原来的局部变量total和totalHarga,这样每次setState触发界面重建时,都会实时计算并显示最新的商品总价。
2. 优化删除商品的逻辑
删除商品后,通过setState直接刷新界面,无需调用getProductData()(除非该方法内部已包含状态更新逻辑):
DataCell( Icon(Icons.delete), onTap: () { setState(() { widget.listProduct.remove(dataProduct); }); }, )
可选优化:让Product支持状态通知
如果后续有更复杂的状态管理需求,可以将Product改为继承ChangeNotifier,通过notifyListeners()通知界面更新,但当前场景下方案1已足够简洁高效。
内容的提问来源于stack exchange,提问作者Ardabily
相关产品推荐
相关产品推荐

