Flutter中FutureBuilder列表子项经弹窗确认删除后如何刷新视图
问题原因
FutureBuilder 只会在所属 Widget 首次构建时执行一次传入的 future 异步任务,后续如果没有触发重构建、且future实例没有变更的话,不会重新执行接口请求拉取最新数据,因此删除操作完成后列表不会自动更新。
方案1:删除成功后重新拉取接口刷新列表
适合数据需要和服务端强一致的场景,操作步骤如下:
- 首先将你的页面改为
StatefulWidget,在 State 中定义变量存储 Future 实例,不要直接把getAllInstructors()写在 FutureBuilder 的future参数里 - 删除操作执行成功后,调用
setState重新给 Future 变量赋值,触发 FutureBuilder 重执行拉取最新数据
示例代码:
class InstructorListPage extends StatefulWidget { const InstructorListPage({super.key}); @override State<InstructorListPage> createState() => _InstructorListPageState(); } class _InstructorListPageState extends State<InstructorListPage> { // 存储异步任务实例 late Future<List<Instructor>> _instructorsFuture; @override void initState() { super.initState(); _instructorsFuture = getAllInstructors(); } // 封装删除逻辑 Future<void> _deleteInstructor(int id) async { // 执行你的删除接口逻辑 await deleteInstructor(id); // 删除成功后重新赋值Future,触发刷新 setState(() { _instructorsFuture = getAllInstructors(); }); } @override Widget build(BuildContext context) { return Scaffold( body: FutureBuilder<List<Instructor>>( // 绑定state中的future变量,不要直接写getAllInstructors() future: _instructorsFuture, builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return const Center(child: CircularProgressIndicator()); } if (snapshot.hasError) { return Center(child: Text('加载失败:${snapshot.error}')); } final instructors = snapshot.data!; return ListView.builder( itemCount: instructors.length, itemBuilder: (context, index) { final instructor = instructors[index]; return InstructorItem( data: instructor, // 侧滑删除点击后的确认回调 onDeleteConfirm: () => _deleteInstructor(instructor.id), ); }, ); }, ), ); } }
方案2:本地更新列表数据,无需二次请求接口
适合删除成功后可确定服务端数据已更新,不需要重复拉取的场景,性能更好:
- 拿到接口返回的数据后在 State 中缓存一份本地列表
- 删除成功后直接操作本地列表移除对应数据,再调用
setState触发重绘即可
示例核心代码片段:
class _InstructorListPageState extends State<InstructorListPage> { List<Instructor> _instructors = []; bool _isLoading = true; String? _error; @override void initState() { super.initState(); _loadData(); } Future<void> _loadData() async { try { final data = await getAllInstructors(); setState(() { _instructors = data; _isLoading = false; }); } catch (e) { setState(() { _error = e.toString(); _isLoading = false; }); } } Future<void> _deleteInstructor(int id) async { await deleteInstructor(id); // 直接移除本地列表中对应数据 setState(() { _instructors.removeWhere((item) => item.id == id); }); } @override Widget build(BuildContext context) { if (_isLoading) return const Center(child: CircularProgressIndicator()); if (_error != null) return Center(child: Text('加载失败:$_error')); return ListView.builder( itemCount: _instructors.length, itemBuilder: (context, index) => InstructorItem( data: _instructors[index], onDeleteConfirm: () => _deleteInstructor(_instructors[index].id), ), ); } }
注意事项
- 不要直接在 FutureBuilder 的
future参数中写future: getAllInstructors(),这种写法会导致每次 Widget 重构建时都重新执行接口请求,造成不必要的性能损耗 - 删除操作执行前建议加 loading 状态,避免用户重复点击触发多次删除请求
内容的提问来源于stack exchange,提问作者Kyrill
相关产品推荐
相关产品推荐

