被解雇的 Dismissible 小部件仍然是颤动树的一部分

Posted

技术标签:

【中文标题】被解雇的 Dismissible 小部件仍然是颤动树的一部分【英文标题】:A dismissed Dismissible widget is still part of the tree in flutter 【发布时间】:2020-02-16 15:06:35 【问题描述】:

我有一个使用provider 进行状态管理和sqlite 数据库的待办事项应用程序。

在应用程序中,我尝试添加 Dismissible 小部件以删除项目。

但问题是当我尝试删除项目时它确实从database 中删除但我在屏幕上收到错误。我是新来的。

控制台出错。

════════ Exception caught by widgets library ═══════════════════════════════════════════════════════
The following assertion was thrown building Dismissible-[<'howll'>](dirty, dependencies: [Directionality], state: _DismissibleState#98163(tickers: tracking 2 tickers)):
A dismissed Dismissible widget is still part of the tree.

Make sure to implement the onDismissed handler and to immediately remove the Dismissible
widget from the application once that handler has fired.
User-created ancestor of the error-causing widget was: 
  TaskListTile file:///C:/Users/adity/Desktop/flutter-app/todoye/lib/widgets/task_list_view.dart:14:22
When the exception was thrown, this was the stack: 
#0      _DismissibleState.build.<anonymous closure> (package:flutter/src/widgets/dismissible.dart:526:11)
#1      _DismissibleState.build (package:flutter/src/widgets/dismissible.dart:533:8)
#2      StatefulElement.build (package:flutter/src/widgets/framework.dart:4047:27)
#3      ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3941:15)
#4      Element.rebuild (package:flutter/src/widgets/framework.dart:3738:5)
...

这是我的代码。

task_list_tile.dart

Dismissible(
      key: Key(taskTitle),
      onDismissed: (direction) 
        deleteCallback();
        Scaffold.of(context)
            .showSnackBar(SnackBar(content: Text("$taskTitle removed.")));
      ,
      child: ListTile(
           title: Text(
          '$taskTitle',  
        ),

task_data.dart

void deleteTask(int id) 
    taskDatabaseManager.deleteTask(id);
    notifyListeners();
  

databse_connection.dart

Future<void> deleteTask(int id) async 
    await openDb();
    await _database.delete(
      'tasks',
      where: 'id = ?',
      whereArgs: [id],
    );
  

task_list_view.dart

class TaskListView extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return Consumer<TaskData>(
      builder: (context, taskData, child) 
        return ListView.builder(
            itemCount: taskData.taskCount,
            itemBuilder: (context, index) 
              return TaskListTile(
                taskTitle: taskData.tasks[index].name,
                isChecked: taskData.tasks[index].isDone,
                checkboxCallback: (checkboxState) 
                  taskData.updateTask(taskData.tasks[index]);
                ,
                deleteCallback: () 
                  taskData.deleteTask(taskData.tasks[index].id);
                ,
              );
            );
      ,
    );
  

【问题讨论】:

您可以将代码从 ListView 发布到 Dismissible 吗? 【参考方案1】:

如果您确定您的可关闭小部件已被删除。尝试修复key。 密钥应该是唯一的。如果tasks的id是唯一的,

key: Key(taskData.tasks[index].id)

如果您没有任何其他恒定且唯一的数据,您可以尝试

key: UniqueKey()

【讨论】:

【参考方案2】:

当您关闭 Dismissible 时,您应该将其从小部件树中移除。在您的情况下,您为taskData 的每个项目显示Dismissible,因此如果您关闭某个项目的Dismissible,您应该从列表中删除该项目。

因此,在deleteCallback 中,在执行deleteTask() 之后,您应该在setState() 中执行taskData.removeAt(index)

【讨论】:

我有点困惑我应该将它们放在task_list_tile.dart 文件上的task_list_view.dart 文件中的哪个位置实际上我在task_list_view.dart 文件中使用Consumer 这就是原因。 task_list_view.dart 中,因为在task_list_tile.dart 中您没有对索引或列表的引用。 但是那里说removeAt 没有定义。

以上是关于被解雇的 Dismissible 小部件仍然是颤动树的一部分的主要内容,如果未能解决你的问题,请参考以下文章

如何解决'已关闭的可关闭小部件仍是树的一部分。'颤抖中

Flutter Dismissible 小部件,带有 confirmDismiss 和 showAlertDialog 停止应用程序

颤动:小部件可以替代自己吗?

在颤动中打开对话框时检测返回按钮按下

如何在颤动中加载主小部件之前显示加载小部件?

一旦视图更改,颤动数字时钟小部件就会导致错误