2

I'm creating a todo list (sort of) app. I have a view where I use a FutureBuilder, it calls a function to fetch the articles from the SQLite db and show as Card. I have a getx_controller.dart which contains the list as observable:

class Controller extends GetxController {
  // this is the list of items
  var itemsList = <Item>[].obs;
}

and I have a items_controller.dart

  // function to delete an item based on item id
  void deleteItem(id) {
    final databaseHelper = DatabaseHelper();

    // remove item at item.id position
    databaseHelper.deleteItem(tableItems, id);

    print('delete item with id $id');
    this.loadAllItems();
  }

the loadAllItems is a function that queries the DB

And finally, the list_builder.dart which contains the FutureBuilder

final itemController = Get.put(ItemsController());

@override
  Widget build(BuildContext context) {
    return FutureBuilder<List<Item>>(
        future: itemController.loadAllItems(),
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.waiting) {
            return CircularProgressIndicator();
          } else if (snapshot.hasData) {
            print(snapshot.data.toString());
            return Obx(() => ListView.builder(
                itemCount: snapshot.data!.length,
                itemBuilder: (context, index) {
                  return Slidable(
                    actionExtentRatio: 0.25,
                    actionPane: SlidableDrawerActionPane(),
                    child: _itemCard(index, snapshot.data![index]),
                    actions: <Widget>[
                      IconSlideAction(
                          caption: 'Elimina',
                          color: Colors.red,
                          icon: Icons.delete,
                          onTap: () {
                            itemController.deleteItem(snapshot.data![index].id);
                            itemController.loadAllItems();
                          }),
                    ],
                    secondaryActions: <Widget>[
                      IconSlideAction(
                        caption: 'Modifica',
                        color: Colors.blue,
                        icon: Icons.edit,
                        onTap: () {},
                      ),
                    ],
                  );
                }));
          } else {
            return Container(
              child: Text('Loading'),
            );
          }
        });
    // });
  }

My issue is that when I tap on "Elimina" (or I create a new item, same procedure), the ListBuilder doesn't refresh the list on the screen, despite of having the itemsList recreated (using getxController.itemsList = RxList.generate(...)) and observable.

mlazzarotto91
  • 103
  • 3
  • 13

1 Answers1

5

You don't need to use FutureBuilder when using observables. This is redundant and makes your code complicated. Instead you should assign the awaited Future (the actual data/items) to your observable list (itemList). And your UI should update automagically.

So your controller should look something like this:

class Controller extends GetxController {
 // this is the list of items
 var itemsList = <Item>[].obs;

 @override
 onInit()async{
   await loadAllItems();
 }

 loadAllItems()async{
     var databaseResponse= await dbHelper.getAll();

  itemList.assignAll(databaseResponse);
  }

}

And your UI build method should just return the observing (Obx) ListView.builder like the following and you are done:

@override
 Widget build(BuildContext context){
   return Obx(() => ListView.builder(
            itemCount: controller.itemList.length,
            itemBuilder: (context, index) {
    var item = comtroller.itemList[index]; // use this item to build your list item
              return Slidable(
S. M. JAHANGIR
  • 4,324
  • 1
  • 10
  • 30