0

我又来了一个问题:如何将 Switch() 小部件与 GetX/Obx() 一起使用?在很多地方,我都读过 GetX/Obx 不需要 StatefullWidget。所以在我的应用程序中,我只使用 StatelessWidgets。问题是我无法使 Switch() 工作,因为 SetState() 在 StatelessWidget 中不可用。

有人可以帮忙吗?谢谢你的好意。A.KOTE

4

3 回答 3

5

GetX + 开关

这是一个使用 GetX 和Switch小部件的复制/粘贴示例,在StatelessWidget.

import 'package:flutter/material.dart';
import 'package:get/get.dart';

/// GetX Controller for holding Switch's current value
class SwitchX extends GetxController {
  RxBool on = false.obs; // our observable

  // swap true/false & save it to observable
  void toggle() => on.value = on.value ? false : true;
}

/// Stateless Page here
class SwitchGetxPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    SwitchX sx = Get.put(SwitchX()); // Instantiate Get Controller, *in* build()

    return Scaffold(
      appBar: AppBar(
        title: Text('Switch Field'),
      ),
      body: SafeArea(
        child: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              // Obx will rebuild Text & Switch when "on" observable changes
              Obx(() => Text('Switch Setting: ${sx.on}')),
              Obx(() => Switch(
                onChanged: (val) => sx.toggle(), 
                value: sx.on.value),
              )
            ],
          ),
        ),
      ),
    );
  }
}

GetX + 状态

使用 GetX,您不需要StatefulWidgets,因为您在小部件之外和“内部”持有“状态” a GetxController.

在上面的示例中,RxBool on = false.obs是应用程序的“状态”。它将是truefalse在您的应用程序的整个生命周期中。

Switch's值发生变化时,您需要重建的任何小部件,将它们放入ObxGetXGetBuilder使用可观察变量。

Obx,GetX将在可观察到的变化时重建自己。 GetBuilder需要你要求update()它重建。就像setState()打电话一样。

为什么Obx在示例中有两个?

为了使痛苦显而易见,Obx/GetX必须直接包装一个可观察变量。

GetX要求您直接在 中使用可观察变量Obx/GetX,而不是像在孩子的孩子中那样进一步嵌套。

例如,下面的这个,会抛出一个错误:

class SwitchGetxPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    SwitchX sx = Get.put(SwitchX());

    return Scaffold(
      appBar: AppBar(
        title: Text('Switch Field'),
      ),
      body: SafeArea(
        child: Center(
          child: Obx(() => MyTextSwitch(sx)), // don't do this, will explode
        ),
      ),
    );
  }
}

class MyTextSwitch extends StatelessWidget {
  final SwitchX sx;

  MyTextSwitch(this.sx);

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        Text('Switch Setting: ${sx.on}'),
        Switch(
            onChanged: (val) => sx.toggle(),
            value: sx.on.value)
      ],
    );
  }
}

下面的这个版本仍然可以,但没有在第一个示例中使用,因为它可能会导致不良习惯(例如重建不需要它的小部件)和上面示例中的错误。请记住,Obx/GetX它的孩子必须有一个可观察的:

class SwitchGetxPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    SwitchX sx = Get.put(SwitchX());

    return Scaffold(
      appBar: AppBar(
        title: Text('Switch Field'),
      ),
      body: SafeArea(
        child: Center(
          child: Obx( // still OK, but rebuilds Column unnecessarily
            () => Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Text('Switch Setting: ${sx.on}'),
                Switch(
                    onChanged: (val) => sx.toggle(),
                    value: sx.on.value)
              ],
            ),
          ),
        ),
      ),
    );
  }
}
于 2021-04-05T17:35:52.303 回答
1

对于简单的 Switch 状态切换,您不应使用控制器。控制器用于更复杂的业务逻辑实现,可以在屏幕之间共享。您可以使用ValueBuilderfromGet包,它可以用更少的代码提供所需的结果。这是一个例子:

Center(
          child: ValueBuilder<bool>(
            initialValue: true,
            builder: (isChecked, updateFn) => Switch(
              value: isChecked,
              onChanged: (newValue) => updateFn(newValue),
            ),
          ),
        ),
于 2020-12-16T10:22:21.910 回答
0

我可以给你一个例子,然后你可以在你的代码中实现。

您可以使用 GetxController 来处理小部件状态。

反例:

class YourController extends GetxController {
  //The current value
  int counter = 0;

  void increment() {
    counter++;
    update(); // use update() to update counter variable on UI when increment be called
  }
}

然后在你的 statelessWidget 你可以听。

class YourWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Center(
      child: GetBuilder<YourController>(
        init: Controller(), // INIT IT ONLY THE FIRST TIME
        builder: (_) => Text(
          '${_.counter}',
        ),
      ),
    ));
  }
}

文档:https ://github.com/jonataslaw/getx/blob/master/documentation/en_US/state_management.md#simple-state-manager

如何更新值?

在控制器中添加一条线

class YourController extends GetxController {
      //New line added
      static YourController  get to => Get.find();
      int counter = 0;

      void increment() {
        counter++;
        update(); // use update() to update counter variable on UI when increment be called
      }
    }

更新用户界面

return Scaffold(
      // body: /*... */
      floatingActionButton: FloatingActionButton(
        child: Text('Hit'),
        onPressed: () {
          //Apply the logic to your Switch widget
          YourController.to.update();
        },
      ),
    );
  }
于 2020-12-15T02:37:09.310 回答