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

Flutter中使用Dismissible组件无法删除列表项问题求助

解决Flutter Dismissible滑动删除崩溃问题

问题现象

滑动删除列表项时触发错误:a dismissed dismissible widget is still part of the tree,应用直接黑屏需重启;但Firestore中对应任务已被删除,重启后列表显示正常。长按删除功能无异常,尝试过UniqueKey()和model.taskId作为Key均未解决。

相关代码片段

任务列表定义

List<TaskModel> tasks = [] ;

列表项构建方法

buildTaskItem(TaskModel model, context) => Dismissible(
                  key: UniqueKey(),
                  onDismissed: (direction) =>
                      AppCubit.get(context).deleteTask(taskId: model.taskId),
                  child: InkWell(
               // 其他业务代码

ListView构建代码

ListView.separated(
                        physics: const NeverScrollableScrollPhysics(),
                        shrinkWrap: true,
                        itemBuilder: (context, index) => buildTaskItem(
                              tasks[index],
                              context,
                            ),
                        separatorBuilder: (context, index) => const SizedBox(
                              height: 8.0,
                            ),
                        itemCount: tasks.length),

Bloc中删除方法

void deleteTask({required taskId}) {
    FirebaseFirestore.instance
        .collection('users')
        .doc(uId)
        .collection('tasks')
        .doc(taskId)
        .delete()
        .then((value) {

      emit(DeletePostSuccessState());
      getTask();
    }).catchError((error) {
      emit(DeletePostErrorState(error));
    });
  }

解决方案

1. 优先更新本地列表,再处理远程数据

崩溃核心原因是:滑动删除后,Dismissible已标记为从Widget树移除,但本地tasks列表未立即更新,Flutter框架仍尝试渲染已被dismissed的组件。

修改deleteTask方法,先从本地列表移除对应任务触发UI刷新,再处理Firestore删除:

void deleteTask({required taskId}) {
    // 先从本地列表移除对应项,立即触发UI更新
    tasks.removeWhere((task) => task.taskId == taskId);
    emit(DeletePostSuccessState());

    // 再处理Firestore远程删除
    FirebaseFirestore.instance
        .collection('users')
        .doc(uId)
        .collection('tasks')
        .doc(taskId)
        .delete()
        .catchError((error) {
      // 可选:如果远程删除失败,可将任务加回本地列表并提示错误
      emit(DeletePostErrorState(error));
    });
  }

2. 使用稳定唯一的Key

放弃UniqueKey()(每次build都会生成新Key,导致Flutter无法跟踪组件状态),改用基于taskId的稳定Key:

buildTaskItem(TaskModel model, context) => Dismissible(
                  key: Key(model.taskId), // 用Firestore文档ID作为稳定唯一Key
                  onDismissed: (direction) =>
                      AppCubit.get(context).deleteTask(taskId: model.taskId),
                  child: InkWell(
               // 其他业务代码

3. 调整状态更新逻辑

避免依赖getTask()重新拉取列表来更新UI,因为网络延迟可能导致本地刚移除的项被重复添加。优先保证本地状态与UI实时同步,远程操作仅做数据持久化。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 02:17:33