Search code examples
sqliteflutterdartprovider

A dismissed Dismissible widget is still part of the tree in flutter


I have a todo app which uses provider for state management and sqlite database.

In the app I am trying to add Dismissible widget to delete item.

But the problem is when I try to delete item It does get deleted from database but I get error on the screen.I am new to flutter.

dismissible image

error in console.

════════ 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)
...

This is my code.

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);
                },
              );
            });
      },
    );
  }
}

Solution

  • When you dismiss a Dismissible, you should remove it from the widget tree. In your case, you are showing a Dismissible for each item of taskData, so if you dismiss the Dismissible of an item you should remove that item from the list.

    So, in the deleteCallback, after doing deleteTask(), you should do taskData.removeAt(index) inside setState().