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

Flutter中实现单按钮表格计算功能的优化方案

问题描述

产品数据表格截图:包含两行产品数据,列依次为Products、Load(Qty)、Bal(Qty)、Amount,初始Amount值均为0。

现有两行产品数据,包含产品名称、Load(qty)、Balance(qty)、Amount列,需按照公式Amount = (load - balance)*2计算每行的Amount值并显示在对应行的Amount字段中。要求仅通过一个名为calculate的按钮实现计算,且避免使用示例中重复定义的变量。

原代码

class MyHomePage extends Stateful Widget {
  const MyHomePage({super.key});

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final loadCntrlr1 = TextEditingController();
  final loadCntrlr2 = TextEditingController();

  final balCntrlr1 = TextEditingController();
  final balCntrlr2 = TextEditingController();
  final amount1 = 0;
  final amount2 = 0;

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        body: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            FittedBox(
              child: DataTable(columns: const [
                DataColumn(
                  label: Text('Products'),
                ),
                DataColumn(
                  label: Text('Load(Qty)'),
                ),
                DataColumn(
                  label: Text('Bal(Qty)'),
                ),
                DataColumn(
                  label: Text('Amount'),
                ),
              ], rows: [
                DataRow(cells: [
                  const DataCell(
                    Text('Furniture'),
                  ),
                  DataCell(
                    TextFormField(
                      keyboardType: TextInputType.number,
                      controller: loadCntrlr1,
                    ),
                  ),
                  DataCell(
                    TextFormField(
                      keyboardType: TextInputType.number,
                      controller: balCntrlr1,
                    ),
                  ),
                  const DataCell(
                    Text('0'),
                  ),
                ]),
                DataRow(cells: [
                  const DataCell(
                    Text('Dhall'),
                  ),
                  DataCell(
                    TextFormField(
                      keyboardType: TextInputType.number,
                      controller: loadCntrlr2,
                    ),
                  ),
                  DataCell(
                    TextFormField(
                      keyboardType: TextInputType.number,
                      controller: balCntrlr2,
                    ),
                  ),
                  const DataCell(
                    Text('0'),
                  ),
                ]),
              ]),
            ),
            ElevatedButton(onPressed: () {}, child: Text('calculate'))
          ],
        ),
      ),
    );
  }
}

优化实现代码

class MyHomePage extends Stateful Widget {
  const MyHomePage({super.key});

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

// 封装单个产品的所有数据
class Product {
  final String name;
  final TextEditingController loadController;
  final TextEditingController balanceController;
  int amount;

  Product({
    required this.name,
    required this.loadController,
    required this.balanceController,
    this.amount = 0,
  });
}

class _MyHomePageState extends State<MyHomePage> {
  // 用列表统一管理所有产品,避免重复定义变量
  final List<Product> products = [
    Product(
      name: 'Furniture',
      loadController: TextEditingController(),
      balanceController: TextEditingController(),
    ),
    Product(
      name: 'Dhall',
      loadController: TextEditingController(),
      balanceController: TextEditingController(),
    ),
  ];

  // 批量计算所有产品的Amount值
  void calculateAmounts() {
    setState(() {
      for (var product in products) {
        // 解析输入值,处理空输入或非数字的情况
        final load = int.tryParse(product.loadController.text) ?? 0;
        final balance = int.tryParse(product.balanceController.text) ?? 0;
        product.amount = (load - balance) * 2;
      }
    });
  }

  @override
  void dispose() {
    // 统一释放所有控制器资源,防止内存泄漏
    for (var product in products) {
      product.loadController.dispose();
      product.balanceController.dispose();
    }
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        body: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            FittedBox(
              child: DataTable(
                columns: const [
                  DataColumn(label: Text('Products')),
                  DataColumn(label: Text('Load(Qty)')),
                  DataColumn(label: Text('Bal(Qty)')),
                  DataColumn(label: Text('Amount')),
                ],
                // 根据产品列表动态生成表格行,减少重复代码
                rows: products.map((product) {
                  return DataRow(cells: [
                    DataCell(Text(product.name)),
                    DataCell(
                      TextFormField(
                        keyboardType: TextInputType.number,
                        controller: product.loadController,
                      ),
                    ),
                    DataCell(
                      TextFormField(
                        keyboardType: TextInputType.number,
                        controller: product.balanceController,
                      ),
                    ),
                    DataCell(Text(product.amount.toString())),
                  ]);
                }).toList(),
              ),
            ),
            ElevatedButton(
              onPressed: calculateAmounts,
              child: const Text('calculate'),
            )
          ],
        ),
      ),
    );
  }
}

核心改进说明

  • 用Product类封装每个产品的名称、输入控制器和计算结果,避免重复定义多个独立变量
  • 通过列表统一管理所有产品数据,便于遍历计算和UI生成
  • 动态生成DataTable的行,消除重复的UI代码
  • 在计算方法中统一处理所有产品的逻辑,点击按钮后通过setState更新UI显示计算结果
  • 统一释放所有控制器资源,避免内存泄漏

内容的提问来源于stack exchange,提问作者Afthal Ad

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 17:00:11