Flutter ListView实例中调用setState删除卡片时报构建期调用错误
问题核心原因
- 传递回调时直接执行了函数:
itemBuilder中给ListCard传delete参数时写的是_callback(),带括号会在Widget构建阶段直接执行该函数,若函数内有setState就会触发「build期间调用setState」的报错。 - 回调调用时未执行函数:
ListCard的IconButton点击逻辑里写的是delete;,没有加括号,回调函数根本不会被执行,所以对应打印不会输出。 - 额外逻辑问题:列表数据
itemList定义为全局final变量,不适合做动态增删,建议移到State类内管理,同时删除逻辑应统一放在父组件处理,不要在子组件直接修改全局数据。
修正后的完整代码
import 'package:flutter/material.dart'; //ItemData used in addnew.dart class ItemData { final String id; final String score; final String title; final String description; ItemData({required this.id, required this.score, required this.title, required this.description}); } class ListRe extends StatefulWidget { const ListRe({Key? key}) : super(key: key); @override State<ListRe> createState() => _ListReState(); } class _ListReState extends State<ListRe> { // 列表数据移到State内管理,不要定义为全局final List<ItemData> itemList = [ ItemData(id: 'one', score: '30', title: 'Title One', description: 'mock description'), ItemData(id: 'two', score: '10', title: 'Title Two', description: 'mock description'), ItemData(id: 'three', score: '20', title: 'Title Three', description: 'mock description'), ]; _callback(ItemData item){ print('delete tapped'); setState(() { // 删除逻辑放到父组件回调内处理 itemList.remove(item); }); } @override Widget build(BuildContext context) { return Scaffold( body: ListView.builder( scrollDirection: Axis.horizontal, itemCount: itemList.length, itemBuilder: (context, index) { // 传函数引用,不要加()执行 return ListCard(item: itemList[index], delete: () => _callback(itemList[index])); }), ); } @override void initState() { super.initState(); sortList(); } sortList() { itemList.sort((item1, item2) => item2.score.compareTo(item1.score)); } } class ListCard extends StatelessWidget { final ItemData item; // 明确声明函数类型 final VoidCallback delete; const ListCard({Key? key, required this.item, required this.delete}) : super(key: key); @override Widget build(BuildContext context) { return Card( child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Column( mainAxisAlignment: MainAxisAlignment.start, children: [ Padding( padding: const EdgeInsets.fromLTRB(0,0,0,0), child: Text(item.title, style: const TextStyle(fontWeight: FontWeight.bold) ), ), Text('Score: ' + item.score), ], ), Column( children: [ IconButton( onPressed: (){ print('delete pressed'); // 加()执行回调 delete(); }, icon: const Icon(Icons.delete)), ], ) ], ), ); } }
内容的提问来源于stack exchange,提问作者Jeremy Parker
相关产品推荐
相关产品推荐

