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

Flutter动态字符串列表访问异常,需生成产品对应映射的技术求助

问题描述

我动态生成了一个字符串列表:

// 我根据产品列表长度声明并生成字符串列表
late final List<String> recovered; 

// 产品列表长度为3
recovered = List.generate(products.length, (index) => "");

随后将该列表赋值给TextField的onChanged方法:

TextField(
  onChanged: (value) {
    recovered[index] = value;
    log("the value is $value");
    setState(() {});
  },
),

我希望将每个生成并赋值的字符串与产品列表对应,动态生成如下格式的映射:{"product": "Noodles", "recovered": "2"}(其中recovered为文本框输入值,product来自产品列表)。但目前通过recovered[index]仅能获取首个索引值,且无法通过指定固定索引(如recovered[1])获取动态生成的各元素。

解决方案

1. 修复TextField的索引绑定问题

核心问题是闭包捕获的index值异常。如果是在循环(比如ListView.builder)里生成TextField,直接使用循环的index会导致所有TextField绑定到最后一个索引。需要在循环内部创建局部变量捕获当前index:

ListView.builder(
  itemCount: products.length,
  itemBuilder: (context, index) {
    // 用局部变量捕获当前索引,避免闭包问题
    final currentIndex = index;
    return TextField(
      onChanged: (value) {
        recovered[currentIndex] = value;
        setState(() {});
      },
      decoration: InputDecoration(
        hintText: "输入${products[currentIndex]}的数值",
      ),
    );
  },
)

2. 规范recovered列表的初始化

在State类中,建议在initState里初始化列表,避免late变量的潜在风险:

class _MyWidgetState extends State<MyWidget> {
  late List<String> recovered;
  final List<String> products = ["Noodles", "Rice", "Bread"];

  @override
  void initState() {
    super.initState();
    // 初始化空字符串列表,长度与产品列表完全匹配
    recovered = List.filled(products.length, "");
  }

  // ... 其他代码
}

3. 生成目标映射列表

遍历产品列表和recovered列表,直接构建所需的映射集合:

List<Map<String, String>> getProductRecoveredMap() {
  List<Map<String, String>> result = [];
  for (int i = 0; i < products.length; i++) {
    result.add({
      "product": products[i],
      "recovered": recovered[i],
    });
  }
  return result;
}

// 使用示例
void printProductMap() {
  final productMap = getProductRecoveredMap();
  log(productMap.toString());
  // 输出示例:[{"product": "Noodles", "recovered": "2"}, {"product": "Rice", "recovered": "5"}, ...]
}

4. 更优雅的方案:使用自定义类(可选)

如果产品有更多属性,用自定义类替代字符串列表会更易维护:

class ProductData {
  final String name;
  String recovered;

  ProductData({required this.name, this.recovered = ""});
}

// 在State中初始化
List<ProductData> productDataList = [];

@override
void initState() {
  super.initState();
  productDataList = products.map((name) => ProductData(name: name)).toList();
}

// 生成TextField
TextField(
  onChanged: (value) {
    productDataList[currentIndex].recovered = value;
    setState(() {});
  },
)

// 生成映射的方式更直观
final productMap = productDataList.map((data) {
  return {
    "product": data.name,
    "recovered": data.recovered,
  };
}).toList();

内容的提问来源于stack exchange,提问作者Victor Ayodeji Ogundola

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 20:15:33