Obx ListView not updating after value changes

637

Solution 1

Try calling refresh() directly on the RxList:

void updateItem(Todo e) {
  /* final int index = _controller.todoData.indexOf(e);
  _controller.todoData[index].done = !e.done; */
  _controller.todoData.firstWhere((Todo i) => i == e).done = !e.done;
  _controller.todoData.refresh(); // <- Here
}

Solution 2

i just modify some code of yours, just change the RxList to simple List and bool variable to RxBool and use obx on bool I'm sharing code

Your Model class and controller class

    class StateController extends GetxController {
      List<Todo> todoData = <Todo>[
        Todo(name: 'todo1', done: true.obs),
        Todo(name: 'todo2', done: false.obs),
        Todo(name: 'todo3', done: true.obs),
        Todo(name: 'todo4', done: false.obs),
        Todo(name: 'todo5', done: false.obs)
      ].obs;
    }
    
    class Todo {
      String? name;
      RxBool? done;
      Todo({this.name, this.done});
    }

your UI Code

    class TestClass extends StatelessWidget {
      TestClass({Key? key}) : super(key: key);
      final StateController _controller = Get.put(StateController());
    
      void updateItem(Todo e) {
        /* final int index = _controller.todoData.indexOf(e);
      _controller.todoData[index].done = !e.done; */
        _controller.todoData.firstWhere((Todo i) => i == e).done!.value =
            !e.done!.value;
        _controller.refresh();
      }
    
      void deleteItem(Todo e) {
        //**this works**
        final int index = _controller.todoData.indexOf(e);
        _controller.todoData.removeAt(index);
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
            backgroundColor: Colors.white,
            body: ListView.builder(
                itemCount: _controller.todoData.length,
                itemBuilder: (_, int i) => TodoItem(
                      item: _controller.todoData[i],
                      updateItem: () => updateItem(_controller.todoData[i]),
                    )));
      }
    }
    
    class TodoItem extends StatelessWidget {
      TodoItem({Key? key, this.item, this.updateItem}) : super(key: key);
      Todo? item;
      VoidCallback? updateItem;
    
      @override
      Widget build(BuildContext context) {
        return ListTile(
          title: Text(
            item!.name!,
            style: TextStyle(color: Colors.black),
          ),
          subtitle: GestureDetector(
            onTap: updateItem,
            child: Obx(() {
              return Text(
                item!.done!.value.toString(),
                style: TextStyle(color: Colors.black),
              );
            }),
          ),
        );
      }
    }
Share:
637
Ajit Kumar
Author by

Ajit Kumar

Updated on January 04, 2023

Comments

  • Ajit Kumar
    Ajit Kumar over 1 year

    I am having a RxList called todoData. On the basis of this list, a ListView.builder builds a list and in each list there is a button. When this button is clicked the done field of the respective item is updated to either true or false. But, though the value is updated the ui is no changing.
    Here's the list:

    class StateController extends GetxController {
      RxList<Todo> todoData = <Todo>[
    Todo(
        name: 'todo1',
        done: true),
    Todo(
        name: 'todo2',
        done: false),
    Todo(
        name: 'todo3',
        done: true),
    Todo(
        name: 'todo4',
        done: false),
    Todo(
        name: 'todo5',
        done: false)
     ].obs;
    }
    

    Controller:

      final StateController _controller = Get.find();
    

    The update function:

    void updateItem(Todo e) {
      /* final int index = _controller.todoData.indexOf(e);
      _controller.todoData[index].done = !e.done; */
      _controller.todoData.firstWhere((Todo i) => i == e).done = !e.done;
      _controller.refresh();
    }
    
    void deleteItem(Todo e) {     //**this works**
      final int index = _controller.todoData.indexOf(e);
      _controller.todoData.removeAt(index);
    }
    

    Ui:

    Obx(() => ListView.builder(
                              itemCount: _controller.todoData.length,
                              itemBuilder: (_, int i) => TodoItem(
                                  item: _controller.todoData[i],
                                  updateItem: () =>
                                      updateItem(_controller.todoData[i]),
                            ))
    

    Any help is greatly appreciated!

    • Arbiter Chil
      Arbiter Chil almost 2 years
      try get builder then update() obx sometime using update kind a messy wont do anything unless add or delete or view
    • anggadaz
      anggadaz almost 2 years
      where your done button that call updateItem?