obx listView在价值更改后未更新

发布于 2025-01-27 09:23:13 字数 1490 浏览 3 评论 0原文

我有一个rxlist称为tododata。在此列表的基础上,listView.builder构建一个列表,在每个列表中都有一个按钮。单击此按钮后,完成相应项目的字段已更新为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]),
                        ))

对任何帮助都非常感谢!

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!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

生生漫 2025-02-03 09:23:13

obx仅对反应性(RX)变量进行的更改做出反应。您当前拥有的唯一反应性变量是rxlist,因此只有对该列表进行的更改才会触发您的obx更新。

当您更改完成时,您正在更改todo而不是列表中的值,因此不对UI进行更新。

解决此问题的一种方法是在更改完成时强制列表中的更新,您可以通过refresh()rxlist refresh()来执行此操作。 > :(

void updateItem(Todo e) {
  _controller.todoData.firstWhere((Todo i) => i == e).done = !e.done;
  _controller.todoData.refresh(); // <- Here
}

还假设e是列表中包含的对象,您可以直接执行e.done =!e.done

Obx only reacts to changes made in reactive (Rx) variables. The only reactive variable you have currently is the RxList, so only changes made to that list will trigger your Obx to update.

When you change done, you're changing a value in Todo, not the list, so no update is made to the UI.

One way to fix this is to force an update in the list when you change done, you can do this by calling refresh() on the RxList:

void updateItem(Todo e) {
  _controller.todoData.firstWhere((Todo i) => i == e).done = !e.done;
  _controller.todoData.refresh(); // <- Here
}

(Also, assuming e is the same object contained in the list, you can do e.done = !e.done directly)

メ斷腸人バ 2025-02-03 09:23:13

我只是修改了您的一些代码,只需将rxlist更改为简单列表和bool变量,然后在bool上使用obx我共享代码

您的模型类和控制器类

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

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),
              );
            }),
          ),
        );
      }
    }
仄言 2025-02-03 09:23:13

您可以在这里做一些事情,以使您的代码按预期工作。

首先,您需要确保您的TODO类实现了可衡量的Mixin。这将使您可以按值而不是参考比较两个todo实例。

其次,您需要在rxList上使用update()方法来更新适当的托多实例的完成字段的值。

第三,您需要在更新完成的字段后在statecontroller上调用refresh()方法,以便更新UI以反映新值。

第四,您应该考虑使用脚步窗口小部件的内置updateItem()方法,而不是将回调转到窗口小部件。这将确保在更改完成字段时正确更新待遇小部件。

There are a few things you can do here to make your code work as expected.

First, you need to make sure that your Todo class implements the Equatable mixin. This will allow you to compare two Todo instances by value rather than by reference.

Second, you need to use the update() method on your RxList to update the value of the done field for the appropriate Todo instance.

Third, you need to call the refresh() method on your StateController after updating the done field so that the UI will be updated to reflect the new value.

Fourth, you should consider using the TodoItem widget's built-in updateItem() method rather than passing a callback to the widget. This will ensure that the TodoItem widget is updated correctly when the done field is changed.

鹿港巷口少年归 2025-02-03 09:23:13

中调用更新功能

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

尝试在OBX已经在构建过程中时,在更新 可能不会发生。 addpostframecallback 当前构建允许完成后,它将允许执行。要更新的UI。

Try Calling the Update Function inside

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

The update may not happen when Obx is already In process of Building. The addPostFrameCallback will execute after the current build has finished and it will allow the UI to be updated.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文