title: How to perform CRUD operations with BLoC pattern?
body: <p>I was learning on flutter how to perform CRUD operations using BLoC pattern, I saw a tutorial online and try to apply it. C,R,U are OK, but deletion is not working. this is the source code.
  Please Help !  </p>
  
  <p>file todo_bloc.dart</p>
  
  <pre><code>import 'package:zencartos/models/todo.dart';
  import 'package:zencartos/repository/todo_repository.dart';
  
  class TodoBloc {
    //Get instance of the Repository
    final _todoRepository = TodoRepository();
    final _todoController = StreamController&lt;List&lt;Todo&gt;&gt;.broadcast();
  
    get todos =&gt; _todoController.stream;
  
    TodoBloc() {
      getTodos();
    }
  
    getTodos({String query}) async {
  
      _todoController.sink.add(await _todoRepository.getAllTodos(query: query));
    }
  
    addTodo(Todo todo) async {
      await _todoRepository.insertTodo(todo);
      getTodos();
    }
  
    updateTodo(Todo todo) async {
      await _todoRepository.updateTodo(todo);
      getTodos();
    }
  
    deleteTodoById(int id) async {
      _todoRepository.deleteTodoById(id);
      getTodos();
    }
  
    dispose() {
      _todoController.close();
    }
  }
  </code></pre>
  
  <p>DAO Page todo_dao.dart</p>
  
  <pre><code>import 'package:zencartos/database/database.dart';
  import 'package:zencartos/models/todo.dart';
  
  
  class TodoDao {
    final dbProvider = DatabaseProvider.dbProvider;
  
    Future&lt;int&gt; createTodo(Todo todo) async{
      final db = await dbProvider.database;
      var result = db.insert(todoTABLE, todo.toDatabaseJson());
      return result;
    }
  
    Future&lt;List&lt;Todo&gt;&gt; getTodos({List&lt;String&gt; columns, String query})
    async{
      final db = await dbProvider.database;
  
      List&lt;Map&lt;String, dynamic&gt;&gt; result;
      if (query != null){
        if (query.isNotEmpty)
          result = await db.query(todoTABLE, columns: columns, where: 'description LIKE ?', whereArgs: ["%$query%"]);
      } else {
        result = await db.query(todoTABLE, columns: columns);
      }
  
      List&lt;Todo&gt; todos = result.isNotEmpty
        ? result.map((item)=&gt; Todo.fromDatabaseJson(item)).toList()
          : [];
      return todos;
    }
  
    //Update Todo record
  
    Future&lt;int&gt; updateTodo(Todo todo) async{
      final db = await dbProvider.database;
  
      var result = await db.update(todoTABLE, todo.toDatabaseJson(),
          where: "id = ?", whereArgs: [todo.id]);
  
      return result;
    }
  
    //Delete Todo records
    Future&lt;int&gt; deleteTodo(int id) async{
      final db = await dbProvider.database;
  
      var result = await db.delete(todoTABLE, where: 'id = ?', whereArgs: [id]);
  
      return result;
    }
  
  
  }
  </code></pre>
  
  <p>Database Page database.dart</p>
  
  <pre><code>import 'dart:io';
  import 'package:path/path.dart';
  import 'package:path_provider/path_provider.dart';
  import 'package:sqflite/sqflite.dart';
  
  
  final todoTABLE = 'Todo';
  
  class DatabaseProvider {
    static final DatabaseProvider dbProvider = DatabaseProvider();
  
    Database _database;
  
    Future&lt;Database&gt; get database async {
      if (_database != null) return _database;
      _database = await createDatabase();
      return _database;
    }
  
    createDatabase() async {
      Directory documentsDirectory = await getApplicationDocumentsDirectory();
  
      String path = join(documentsDirectory.path, "ReactiveTodo");
  
      var database = await openDatabase(path, version: 1, onCreate: initDB, onUpgrade: onUpgrade);
      return database;
    }
  
    void onUpgrade(Database database, int oldVersion, int newVersion){
      if (newVersion &gt; oldVersion){}
    }
  
    void initDB(Database database, int version) async{
      await database.execute("CREATE TABLE $todoTABLE ("
          "id INTEGER PRIMARY KEY, "
          "description TEXT, "
          "is_done INTEGER "
          ")");
    }
  }
  </code></pre>
  
  <p>Model page todo.dart</p>
  
  <pre><code>
  class Todo{
  
    int id;
    String description;
    bool isDone = false;
  
  
    Todo({this.id, this.description, this.isDone = false});
  
    factory Todo.fromDatabaseJson(Map&lt;String, dynamic&gt; data) =&gt; Todo(
      id: data['data'],
      description: data['description'],
  
      isDone: data['is_done'] == 0 ? false : true,
    );
  
    Map&lt;String, dynamic&gt; toDatabaseJson() =&gt; {
  
      "id": this.id,
      "description": this.description,
      "is_done": this.isDone == false ? 0 : 1,
    };
  }
  </code></pre>
  
  <p>View page home_Page2.dart</p>
  
  <pre><code>import 'package:flutter/services.dart';
  import 'package:zencartos/bloc/todo_bloc.dart';
  import 'package:zencartos/models/todo.dart';
  
  
  class HomePage2 extends StatelessWidget {
    HomePage2({Key key, this.title}) : super(key: key);
    final TodoBloc todoBloc = TodoBloc();
    final String title;
  
    //Allows Todo card to be dismissable horizontally
    final DismissDirection _dismissDirection = DismissDirection.horizontal;
  
    @override
    Widget build(BuildContext context) {
      SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.dark.copyWith(
          statusBarColor: Colors.white,
          systemNavigationBarColor: Colors.white,
          systemNavigationBarIconBrightness: Brightness.dark,
          statusBarBrightness: Brightness.dark));
      return Scaffold(
          resizeToAvoidBottomPadding: false,
          body: SafeArea(
              child: Container(
                  color: Colors.white,
                  padding:
                  const EdgeInsets.only(left: 2.0, right: 2.0, bottom: 2.0),
                  child: Container(
                    //This is where the magic starts
                      child: getTodosWidget()))),
          bottomNavigationBar: BottomAppBar(
            color: Colors.white,
            child: Container(
              decoration: BoxDecoration(
                  border: Border(
                    top: BorderSide(color: Colors.grey, width: 0.3),
                  )),
              child: Row(
                mainAxisSize: MainAxisSize.max,
                children: &lt;Widget&gt;[
                  IconButton(
                      icon: Icon(
                        Icons.menu,
                        color: Colors.indigoAccent,
                        size: 28,
                      ),
                      onPressed: () {
                        //just re-pull UI for testing purposes
                        todoBloc.getTodos();
                      }),
                  Expanded(
                    child: Text(
                      "Todo",
                      style: TextStyle(
                          color: Colors.black,
                          fontWeight: FontWeight.w600,
                          fontFamily: 'RobotoMono',
                          fontStyle: FontStyle.normal,
                          fontSize: 19),
                    ),
                  ),
                  Wrap(children: &lt;Widget&gt;[
                    IconButton(
                      icon: Icon(
                        Icons.search,
                        size: 28,
                        color: Colors.indigoAccent,
                      ),
                      onPressed: () {
                        _showTodoSearchSheet(context);
                      },
                    ),
                    Padding(
                      padding: EdgeInsets.only(right: 5),
                    )
                  ])
                ],
              ),
            ),
          ),
          floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
          floatingActionButton: Padding(
            padding: EdgeInsets.only(bottom: 25),
            child: FloatingActionButton(
              elevation: 5.0,
              onPressed: () {
                _showAddTodoSheet(context);
              },
              backgroundColor: Colors.white,
              child: Icon(
                Icons.add,
                size: 32,
                color: Colors.indigoAccent,
              ),
            ),
          ));
    }
  
    void _showAddTodoSheet(BuildContext context) {
      final _todoDescriptionFormController = TextEditingController();
      showModalBottomSheet(
          context: context,
          builder: (builder) {
            return new Padding(
              padding: EdgeInsets.only(
                  bottom: MediaQuery.of(context).viewInsets.bottom),
              child: new Container(
                color: Colors.transparent,
                child: new Container(
                  height: 230,
                  decoration: new BoxDecoration(
                      color: Colors.white,
                      borderRadius: new BorderRadius.only(
                          topLeft: const Radius.circular(10.0),
                          topRight: const Radius.circular(10.0))),
                  child: Padding(
                    padding: EdgeInsets.only(
                        left: 15, top: 25.0, right: 15, bottom: 30),
                    child: ListView(
                      children: &lt;Widget&gt;[
                        Row(
                          mainAxisSize: MainAxisSize.min,
                          crossAxisAlignment: CrossAxisAlignment.center,
                          children: &lt;Widget&gt;[
                            Expanded(
                              child: TextFormField(
                                controller: _todoDescriptionFormController,
                                textInputAction: TextInputAction.newline,
                                maxLines: 4,
                                style: TextStyle(
                                    fontSize: 21, fontWeight: FontWeight.w400),
                                autofocus: true,
                                decoration: const InputDecoration(
                                    hintText: 'I have to...',
                                    labelText: 'New Todo',
                                    labelStyle: TextStyle(
                                        color: Colors.indigoAccent,
                                        fontWeight: FontWeight.w500)),
                                validator: (String value) {
                                  if (value.isEmpty) {
                                    return 'Empty description!';
                                  }
                                  return value.contains('')
                                      ? 'Do not use the @ char.'
                                      : null;
                                },
                              ),
                            ),
                            Padding(
                              padding: EdgeInsets.only(left: 5, top: 15),
                              child: CircleAvatar(
                                backgroundColor: Colors.indigoAccent,
                                radius: 18,
                                child: IconButton(
                                  icon: Icon(
                                    Icons.save,
                                    size: 22,
                                    color: Colors.white,
                                  ),
                                  onPressed: () {
                                    final newTodo = Todo(
                                        description:
                                        _todoDescriptionFormController
                                            .value.text);
                                    if (newTodo.description.isNotEmpty) {
                                      /*Create new Todo object and make sure
                                      the Todo description is not empty,
                                      because what's the point of saving empty
                                      Todo
                                      */
                                      todoBloc.addTodo(newTodo);
  
                                      //dismisses the bottomsheet
                                      Navigator.pop(context);
                                    }
                                  },
                                ),
                              ),
                            )
                          ],
                        ),
                      ],
                    ),
                  ),
                ),
              ),
            );
          });
    }
  
    void _showTodoSearchSheet(BuildContext context) {
      final _todoSearchDescriptionFormController = TextEditingController();
      showModalBottomSheet(
          context: context,
          builder: (builder) {
            return new Padding(
              padding: EdgeInsets.only(
                  bottom: MediaQuery.of(context).viewInsets.bottom),
              child: new Container(
                color: Colors.transparent,
                child: new Container(
                  height: 230,
                  decoration: new BoxDecoration(
                      color: Colors.white,
                      borderRadius: new BorderRadius.only(
                          topLeft: const Radius.circular(10.0),
                          topRight: const Radius.circular(10.0))),
                  child: Padding(
                    padding: EdgeInsets.only(
                        left: 15, top: 25.0, right: 15, bottom: 30),
                    child: ListView(
                      children: &lt;Widget&gt;[
                        Row(
                          mainAxisSize: MainAxisSize.min,
                          crossAxisAlignment: CrossAxisAlignment.center,
                          children: &lt;Widget&gt;[
                            Expanded(
                              child: TextFormField(
                                controller: _todoSearchDescriptionFormController,
                                textInputAction: TextInputAction.newline,
                                maxLines: 4,
                                style: TextStyle(
                                    fontSize: 18, fontWeight: FontWeight.w400),
                                autofocus: true,
                                decoration: const InputDecoration(
                                  hintText: 'Search for todo...',
                                  labelText: 'Search *',
                                  labelStyle: TextStyle(
                                      color: Colors.indigoAccent,
                                      fontWeight: FontWeight.w500),
                                ),
                                validator: (String value) {
                                  return value.contains('@')
                                      ? 'Do not use the @ char.'
                                      : null;
                                },
                              ),
                            ),
                            Padding(
                              padding: EdgeInsets.only(left: 5, top: 15),
                              child: CircleAvatar(
                                backgroundColor: Colors.indigoAccent,
                                radius: 18,
                                child: IconButton(
                                  icon: Icon(
                                    Icons.search,
                                    size: 22,
                                    color: Colors.white,
                                  ),
                                  onPressed: () {
                                    /*This will get all todos
                                    that contains similar string
                                    in the textform
                                    */
                                    todoBloc.getTodos(
                                        query:
                                        _todoSearchDescriptionFormController
                                            .value.text);
                                    //dismisses the bottomsheet
                                    Navigator.pop(context);
                                  },
                                ),
                              ),
                            )
                          ],
                        ),
                      ],
                    ),
                  ),
                ),
              ),
            );
          });
    }
  
    Widget getTodosWidget() {
      return StreamBuilder(
        stream: todoBloc.todos,
        builder: (BuildContext context, AsyncSnapshot&lt;List&lt;Todo&gt;&gt; snapshot) {
          return getTodoCardWidget(snapshot);
        },
      );
    }
  
    Widget getTodoCardWidget(AsyncSnapshot&lt;List&lt;Todo&gt;&gt; snapshot) {
      if (snapshot.hasData) {
        return snapshot.data.length != 0
            ? ListView.builder(
          itemCount: snapshot.data.length,
          itemBuilder: (context, itemPosition) {
            Todo todo = snapshot.data[itemPosition];
            final Widget dismissibleCard = new Dismissible(
              background: Container(
                child: Padding(
                  padding: EdgeInsets.only(left: 10),
                  child: Align(
                    alignment: Alignment.centerLeft,
                    child: Text(
                      "Deleting",
                      style: TextStyle(color: Colors.white),
                    ),
                  ),
                ),
                color: Colors.redAccent,
              ),
              onDismissed: (direction) {
                todoBloc.deleteTodoById(todo.id);
              },
              direction: _dismissDirection,
              key: new ObjectKey(todo),
              child: Card(
                  shape: RoundedRectangleBorder(
                    side: BorderSide(color: Colors.grey[200], width: 0.5),
                    borderRadius: BorderRadius.circular(5),
                  ),
                  color: Colors.white,
                  child: ListTile(
                    leading: InkWell(
                      onTap: () {
                        //Reverse the value
                        todo.isDone = !todo.isDone;
                        todoBloc.updateTodo(todo);
                      },
                      child: Container(
                        //decoration: BoxDecoration(),
                        child: Padding(
                          padding: const EdgeInsets.all(15.0),
                          child: todo.isDone
                              ? Icon(
                            Icons.done,
                            size: 26.0,
                            color: Colors.indigoAccent,
                          )
                              : Icon(
                            Icons.check_box_outline_blank,
                            size: 26.0,
                            color: Colors.tealAccent,
                          ),
                        ),
                      ),
                    ),
                    title: Text(
                      todo.description,
                      style: TextStyle(
                          fontSize: 16.5,
                          fontFamily: 'RobotoMono',
                          fontWeight: FontWeight.w500,
                          decoration: todo.isDone
                              ? TextDecoration.lineThrough
                              : TextDecoration.none),
                    ),
                  )),
            );
            return dismissibleCard;
          },
        )
            : Container(
            child: Center(
              //this is used whenever there 0 Todo
              //in the data base
              child: noTodoMessageWidget(),
            ));
      } else {
        return Center(
          child: loadingData(),
        );
      }
    }
  
    Widget loadingData() {
      todoBloc.getTodos();
      return Container(
        child: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: &lt;Widget&gt;[
              CircularProgressIndicator(),
              Text("Loading...",
                  style: TextStyle(fontSize: 19, fontWeight: FontWeight.w500))
            ],
          ),
        ),
      );
    }
  
    Widget noTodoMessageWidget() {
      return Container(
        child: Text(
          "Start adding Todo...",
          style: TextStyle(fontSize: 19, fontWeight: FontWeight.w500),
        ),
      );
    }
  
    dispose() {
      todoBloc.dispose();
    }
  }
  </code></pre>
  
  <p>repository page todo_repository.dart</p>
  
  <pre><code>import 'package:zencartos/models/todo.dart';
  
  class TodoRepository {
    final todoDao = TodoDao();
  
    Future getAllTodos({String query}) =&gt; todoDao.getTodos(query: query);
  
    Future insertTodo(Todo todo) =&gt; todoDao.createTodo(todo);
  
    Future updateTodo(Todo todo) =&gt; todoDao.updateTodo(todo);
  
    Future deleteTodoById(int id) =&gt; todoDao.deleteTodo(id);
  
    //We are not going to use this in the demo
    //Future deleteAllTodos() =&gt; todoDao.deleteAllTodos();
  }
  </code></pre>