【问题标题】:GetX + Flutter: how to make Obx rebuild when updating a list inside an entity (and in general, what triggers an Obx rebuild)?GetX + Flutter:在更新实体内的列表时如何使 Obx 重建(一般来说,是什么触发了 Obx 重建)?
【发布时间】:2021-11-23 05:53:50
【问题描述】:

我正在开发一个使用 GetX 进行状态管理的 Flutter 项目。

我们有一些包含 List 属性的实体。简化版本类似于:

class UserFees extends Equatable {
  final String userId;
  final List<double> fees;
  UserFees({required this.userId, this.fees = const []});

  void addFee(double newFee) => fees.add(newFee);

  @override
  List<Object> get props => [fees];

  // Alternatively, we have also tried to:
  @override
  bool operator ==(Object other) =>
    identical(this, other) ||
    other is UserFees &&
    runtimeType == other.runtimeType &&
    listEquals(fees, (other as UserFees).fees);

  @override
  int get hashCode => // I do not remember the calculus we'd used,
                      // but it did at least change when new item was added;
}

这个实体在控制器中使用:

class MyController extends GetxController {
  final Rx<UserFees> userFees;

  void addFee(double newFee) {
    userFees.addFee(newFee);
    // We have tried calling update() to no effect
  }
}

当我在带有 Obx 的 Widget 中使用它时,当我将项目添加到列表时它不会重建,即使对象的 hashCode 已更新。

Widget build(BuildContext context) {
  return Scaffold(
    body: Obx(() => Column(children:
        ...controller.userFees.fees.map(
            (item) => Text(item.toString()
          );
        ),
      ),
    floatingActionButton: IconButton(
        icon: const Icon(Icons.add),
        onPressed: controller.addFee(0.1)
      ),
    );
  );
}

我们的团队通过将实体内部的 List 转换为 RxList 来完成这项工作,但这并不理想,因为我们不想将实体与 GetX 或 RxDart 耦合。

GetX 文档在这些细节上的内容很差,而且源代码很难理解,至少对我来说是这样。那么,任何人都可以向我解释 Obx 是如何知道可观察对象已更改的吗?它会查看 hashCode 吗?只有当我的类是不可变的并且我在将项目添加到列表时完全重建对象时,它才会重建?

【问题讨论】:

    标签: flutter rxdart flutter-getx


    【解决方案1】:

    我觉得有些建议对你有帮助。

    在 MyController 中,您正在使用

     final Rx<UserFees> userFees;
    

    这意味着您声明为 Rx,但您并没有使其成为可观察的。要使您的 UserFees 可观察,您应该使用

     final Rx<UserFees> userFees = 0.0.obs; // if it's type is double;
    

    接下来,在您的实体中,如果您认为某个变量的值正在发生变化,并且您希望在 UI 中反映该值。那么你也应该使那个 Observable。

    【讨论】:

    • 我会说调用userFees.refresh() 也可能是正确的,因为UserFees 是一个类。
    • @RohitSingh 我认为 UserFees 实体提示可能会有用,谢谢。关于使实体内部的变量也可观察,这就是我们所做的,我们不想这样做,因为实体与 GetX 耦合。我们公司经常在项目之间复用代码,但并不是所有项目都使用GetX。
    • @NathanielJohnson 我认为您的提示也会很有用,谢谢。
    • @NathanielJohnson 如果您使用的是 Obx() 小部件,则不需要使用 userFees.refresh()。因为 Obx() 会在需要时自动更新小部件。如果您使用 GetBuilder((controller) => SomeWidget());那么在这种情况下,您需要手动刷新 UI。
    • Obx(和其他所有人)不会对对象内部的列表进行深度刷新。这总是一个问题。出于这个原因,我已经停止使用 observables,只是在控制器中刷新/更新/notifyListeners。
    猜你喜欢
    • 2022-11-04
    • 2021-09-15
    • 1970-01-01
    • 2021-11-11
    • 2021-11-07
    • 2022-10-17
    • 2021-07-11
    • 2022-01-02
    • 2021-11-15
    相关资源
    最近更新 更多