You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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();
                      },
                    )
           ],
         );
       }
     ),
 ),

问题原因

  1. totalHarga是在List.generate初始化时计算的固定字符串,点击加减按钮后,局部变量total的更新无法同步到界面显示的totalHarga。
  2. 直接修改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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 03:32:12