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++; }); }, ), ); }, ); }
额外优化建议
- 如果需要刷新数据:可以单独调用
_loadItems()方法(比如下拉刷新时),而不是依赖setState()重新触发请求。 - 状态管理扩展:如果你的页面逻辑更复杂(比如多个组件需要共享这个列表状态),可以考虑使用Provider、Riverpod等状态管理库,把列表状态抽离到全局或局部状态容器中。
- 模型类优化:可以给
ItemModel添加命名构造函数,或者使用json_serializable来自动解析JSON,减少手动解析的出错概率。
内容的提问来源于stack exchange,提问作者kepitingrebus
相关产品推荐
相关产品推荐

