在Flutter中,被解除的可解除小部件仍然是树的一部分。

5
我有一个待办事项应用程序,使用 provider 进行状态管理和 sqlite 数据库。
在应用程序中,我试图添加 Dismissible widget 以删除项目。
但问题是,当我尝试删除项目时,它确实从 database 中删除了,但屏幕上出现错误。我对 Flutter 不熟悉。

dismissible image

控制台中出现错误。

════════ 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的代码贴出来吗? - Pablo Barrera
3个回答

10

如果你确定你的可消除小部件被移除了,请尝试修复 key。 Key 应该是唯一的。如果 tasks 的 id 是唯一的,

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

如果您没有其他常量且独特的数据,可以尝试

key: UniqueKey()

7
当您关闭一个Dismissible时,您应该将其从小部件树中移除。在您的情况下,您正在为taskData的每个项目显示一个Dismissible,因此如果您关闭项目的Dismissible,则应该从列表中删除该项。
因此,在deleteCallback中,在执行deleteTask()后,您应该在setState()内执行taskData.removeAt(index)

我有点困惑应该把它们放在哪个文件里,是在 task_list_view.dart 文件还是在 task_list_tile.dart 文件中?实际上我在 task_list_view.dart 文件中使用了 Consumer - aditya kumar
task_list_view.dart 中,因为在 task_list_tile.dart 中你没有索引或列表的引用。 - Pablo Barrera
但是那里显示removeAt未定义。 - aditya kumar

0
我使用了UniqueKey()而不是Key(taskData.tasks[index].id),这样做是正确的。

您的答案可以通过提供额外的支持信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便其他人可以确认您的答案是否正确。您可以在帮助中心找到关于如何撰写好答案的更多信息。 - Community

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接