flutter Obx ListView在值更改后不更新

ttp71kqs  于 2023-05-19  发布在  Flutter
关注(0)|答案(4)|浏览(660)

我有一个RxList,叫做todoData。在此列表的基础上,ListView.builder构建了一个列表,每个列表中都有一个按钮。单击此按钮后,相应项目的done字段将更新为truefalse。但是,尽管值更新了,但ui没有变化。
以下是名单:

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

控制器:

final StateController _controller = Get.find();

更新功能:

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]),
                        ))

任何帮助都非常感谢!

u2nhd7ah

u2nhd7ah1#

尝试直接在RxList上调用refresh()

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
}
kmynzznz

kmynzznz2#

我只是修改了你的一些代码,只是改变了RxList简单列表和布尔变量RxBool和使用obx的布尔我分享代码
您的Model类和控制器类

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

您的UI代码

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

2cmtqfgy3#

这里有几件事你可以做,使你的代码按预期工作。
首先,您需要确保Todo类实现了Equatable mixin。这将允许您通过值而不是引用来比较两个Todo示例。
其次,您需要使用RxList上的update()方法来更新适当Todo示例的done字段的值。
第三,在更新done字段之后,需要调用StateController上的refresh()方法,以便更新UI以反映新值。
第四,您应该考虑使用TodoItem小部件的内置updateItem()方法,而不是向小部件传递回调。这将确保在done字段更改时TodoItem小部件正确更新。

disbfnqx

disbfnqx4#

尝试调用内部的更新函数

WidgetsBinding.instance.addPostFrameCallback((_) {
            // Update Code Goes Here //
 });

当Obx已经在构建过程中时,更新可能不会发生。addPostFrameCallback将在当前构建完成后执行,并允许更新UI。

相关问题