简体   繁体   English

使用带有 GetX/Obx() 的 Switch() 小部件

[英]Using a Switch() widget with GetX/Obx()

I am back with the question: How can I use the Switch() widget with GetX/Obx()?我又来了一个问题:如何将 Switch() 小部件与 GetX/Obx() 一起使用? At many places i have read that with GetX/Obx no need of StatefullWidget.在很多地方,我都读过 GetX/Obx 不需要 StatefullWidget。 So in my app I use only StatelessWidgets.所以在我的应用程序中,我只使用 StatelessWidgets。 Problem is that i can not make a Switch() working because SetState() is not usable in StatelessWidget.问题是我无法使 Switch() 工作,因为 SetState() 在 StatelessWidget 中不可用。

Can someone help, please?有人可以帮忙吗? Thank for your kindness.谢谢你的好意。 A.KOTE A.KOTE

For simple Switch state toggle you should not use a controller.对于简单的开关 state 切换,您不应使用 controller。 Controller is for more complex business logic implementation which can be shared among screens. Controller 用于更复杂的业务逻辑实现,可以在屏幕之间共享。 You can use ValueBuilder from Get package which can give desired result with less code.您可以使用Get ValueBuilder中的 ValueBuilder,它可以用更少的代码提供所需的结果。 Here is an example:这是一个例子:

Center(
          child: ValueBuilder<bool>(
            initialValue: true,
            builder: (isChecked, updateFn) => Switch(
              value: isChecked,
              onChanged: (newValue) => updateFn(newValue),
            ),
          ),
        ),

I can give you an example and then you can implement in your code.我可以给你一个例子,然后你可以在你的代码中实现。

You can use a GetxController to handle the widget state.您可以使用 GetxController 来处理小部件 state。

Counter example:反例:

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

Then in your statelessWidget you can listen.然后在你的 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}',
        ),
      ),
    ));
  }
}

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

How can you update the value?如何更新值?

Add a line to your controller在您的 controller 中添加一行

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

Update the UI更新用户界面

return Scaffold(
      // body: /*... */
      floatingActionButton: FloatingActionButton(
        child: Text('Hit'),
        onPressed: () {
          //Apply the logic to your Switch widget
          YourController.to.update();
        },
      ),
    );
  }

GetX + Switch GetX + 开关

Here's a copy/paste example of using GetX with a Switch widget, within a StatelessWidget .这是在StatelessWidget中使用 GetX 和Switch小部件的复制/粘贴示例。

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 + State GetX + State

With GetX you don't need StatefulWidgets because you're holding "state" outside of widgets and "inside" a GetxController .使用 GetX,您不需要StatefulWidgets ,因为您在小部件之外和“内部”持有“状态” GetxController

In the example above, RxBool on = false.obs is the "state" of your application.在上面的示例中, RxBool on = false.obs是应用程序的“状态”。 It will be true or false throughout the life of your app.在您的应用程序的整个生命周期中,这将是truefalse

When Switch's value changes, any widgets you need rebuilt, put them in Obx , GetX or GetBuilder and use the observable variable.Switch's值发生变化时,您需要重建的任何小部件,将它们放入ObxGetXGetBuilder并使用 observable 变量。

Obx , GetX will rebuild themselves whenever their observable changes. ObxGetX将在其可观察到的变化时重建自己。 GetBuilder requires you call update() for it to rebuild. GetBuilder要求您调用update()来重建它。 Just like a setState() call.就像setState()调用一样。

Why Two Obx in Example?为什么在示例中有两个Obx

To make painfully obvious that Obx/GetX must directly wrap an observable variable.为了使Obx/GetX必须直接包装一个可观察的变量,这一点非常明显。

GetX asks you to use observable variables directly in Obx/GetX , not further nested down, like in child of a child. GetX要求您直接在Obx/GetX中使用可观察变量,而不是像在孩子的孩子中那样进一步嵌套。

For example, this below, will throw an Error:例如,下面的这个,会抛出一个错误:

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

This version below is still OK, but not used in first example, as it may lead to bad habits (like rebuilding widgets that don't need it) & errors like the example immediately above.下面的这个版本仍然可以,但没有在第一个示例中使用,因为它可能会导致不良习惯(例如重建不需要它的小部件)和上面示例中的错误。 Just remember that Obx/GetX must have an observable in its child:请记住, Obx/GetX的子项中必须有一个 observable:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM