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

Flutter中点击ListTile时尾部数字无法递增始终返回0问题(使用FutureBuilder场景)

问题根源分析

你遇到的核心问题是:每次调用setState()触发UI重建时,FutureBuilder会重新执行传入的_getItems()方法,重新从API获取数据并创建全新的ItemModel实例——这就导致之前修改的countSelected值被重置为初始的0,因为你操作的旧实例已经被新创建的实例覆盖了。

解决方案:将数据缓存到State变量中

我们需要把从API获取到的列表数据保存到Widget的State变量里,而不是每次build都重新请求。这样修改后,setState()只会更新UI,不会重新拉取数据和创建新的模型实例。

修改后的完整代码示例

1. 在State类中添加缓存变量和初始化逻辑

class _YourPageState extends State<YourPage> {
  // 用这个变量缓存从API获取的列表,避免每次build重新请求
  List<ItemModel>? _cachedItems;
  bool _isLoading = true;

  @override
  void initState() {
    super.initState();
    // 页面初始化时只请求一次数据
    _loadItems();
  }

  // 单独封装数据请求逻辑
  Future<void> _loadItems() async {
    _cachedItems = await _getItems();
    setState(() {
      _isLoading = false;
    });
  }

  // 保留你原来的API请求方法
  Future<List<ItemModel>> _getItems() async {
    List<ItemModel> listItems = [];
    var url = Uri.parse(BASEURLLOCAL.apiGetItems);
    var data = await http.get(url);
    var jsonData = jsonDecode(data.body);
    for (var p in jsonData) {
      ItemModel item = ItemModel(
        p["name"],
        p["price"],
        p["image"],
      );
      listItems.add(item);
    }
    return listItems;
  }

  // ... 下面是build方法
}

2. 重构Build方法,使用缓存数据

@override
Widget build(BuildContext context) {
  // 加载状态判断
  if (_isLoading) {
    return const Center(child: CircularProgressIndicator());
  }

  // 空数据判断
  if (_cachedItems == null || _cachedItems!.isEmpty) {
    return const Center(child: Text("暂无商品数据"));
  }

  // 使用缓存的列表构建ListView
  return ListView.builder(
    shrinkWrap: true,
    itemCount: _cachedItems!.length,
    itemBuilder: (BuildContext context, int idx) {
      final currentItem = _cachedItems![idx];
      return Card(
        child: ListTile(
          leading: Image.network(BASEURLLOCAL.imgItem + currentItem.image),
          title: Text(currentItem.name),
          subtitle: Text(currentItem.price),
          trailing: Text(currentItem.countSelected.toString()),
          onTap: () {
            setState(() {
              // 直接修改缓存列表中的实例属性,不会被重置
              currentItem.countSelected++;
            });
          },
        ),
      );
    },
  );
}
额外优化建议
  1. 如果需要刷新数据:可以单独调用_loadItems()方法(比如下拉刷新时),而不是依赖setState()重新触发请求。
  2. 状态管理扩展:如果你的页面逻辑更复杂(比如多个组件需要共享这个列表状态),可以考虑使用Provider、Riverpod等状态管理库,把列表状态抽离到全局或局部状态容器中。
  3. 模型类优化:可以给ItemModel添加命名构造函数,或者使用json_serializable来自动解析JSON,减少手动解析的出错概率。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 17:37:37