使用 GetX observables 时,哪些 UI 小部件需要封装在 Obx 中?

时间:2021-08-01 15:33:18

标签: flutter flutter-getx

为了学习 GetX,我创建了一个简单的控制器类:

class MyDataController extends GetxController {
  RxString aString = ''.obs;

  void updateString(String s) {
    aString.value = s;
  }
}

aString 的值显示在两个类中:AppBar(此处未讨论)和另一个设置并显示 aString 的类:

class Level1 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final MyDataController controller = Get.find();
    final textController = TextEditingController();
    return Column(
      children: [
        TextField(
          controller: textController,
          onChanged: (_) {
            controller.updateString(textController.text);
          },
        ),
        Text(controller.aString.value),
      ],
    );
  }
}

我不知道哪些小部件需要包含在 Obx() 的实例中。

如果我Text()(显示小部件)包装在 Obx 实例中,它会在 TextField()(输入小部件)更改时更新。如果我TextField() 小部件包装在一个 Obx 实例中,我会收到一条错误消息:

<块引用>

构建 Obx(has builder,dirty, 状态:_ObxState#019a0): [Get] 已检测到 GetX 的不当使用。 您应该只对将更新的特定小部件使用 GetX 或 Obx。 如果您看到此错误,您可能没有在 GetX/Obx 中插入任何可观察变量 或将它们插入 GetX 认为适合更新的范围之外 (例如:GetX => HeavyWidget => variableObservable)。 如果您需要更新父小部件和子小部件,请将每个小部件包装在 Obx/GetX 中。

一切似乎都很清楚:显示状态的小部件必须包含在 Obx() 实例中才能显示更新的变量。这是完全有道理的。更改状态的小部件不需要包装在 Obx() 实例中。

不过,我很困惑,因为如果我将两个小部件包装在单独的 Obx() 实例中,我会收到错误消息。但是,如果我将整个 Column() 包装在一个 Obx() 实例中,则当 TextField() 更改时,文本会正确更新。 ...我的理解中缺少什么?

1 个答案:

答案 0 :(得分:3)

当您将 Text 小部件包装在 Obx 中时,您已经掌握了所有内容。实际上,最好仅包装需要在 Obx 中更新的最小小部件,在本例中为 Text 小部件。

让我解释一下您尝试测试的情况:

案例 1:当您仅将 Text 小部件包装在 Obx 中时(最好的做法)

这个案例恰好是最好和最受鼓励的方法。在这种情况下,当控制器 (MyDataController) 中 aString 的值发生变化时,Obx 会被通知从头开始重新构建受影响的 Text 小部件,并且这正是 GetX 的目标。

案例 2:当您将 Text && 和 TextField 小部件同时包装在 Obx 中时(这会引发错误)。

在本例中,您已将 TextTextField 小部件都封装在 Obx 中,因此我们可以让 case 1 说明 Text 小部件。 现在,转到 TextField 小部件,会发生错误,因为 TexField 小部件不以任何方式依赖于任何 obs-value(可观察值)。 请务必注意,在提供给 textField 的 onChanged 回调中,在 updateString 上调用的方法 controller 对 TextField 的参数没有任何影响,因此这会导致 GetX 抛出错误,因为您正在尝试强制更新/重建一个不需要重建的小部件。

案例 3:当您将整列包裹在 Obx 中时(不会抛出错误,但不是最佳实践)。

在这种情况下,小部件的构建不会有任何错误,因为 Text 小部件(位于列内)依赖于 aString 的值。因此,让我们看看调用 updateString 方法时会发生什么。 当 updateString 被调用时,整个 Column 被重建(连同 TextFieldText 小部件,这个动作也会导致值在要更新的 Text 小部件。 现在,您可以理解为什么这第三种情况可能是有害的,如果您尝试将整个应用程序包装在 Obx 中,那么您的整个应用程序将不得不重新构建(这确实会对您的应用程序的性能产生负面影响。当然 GetX 有办法不允许这样做,因此当您尝试在 Obx 或 GetX 中包装 HeavyWidget 时会引发错误。