TextEditingController与OnChanged

时间:2019-07-05 13:47:21

标签: flutter dart

相对于TextField的OnChanged事件,我正在寻找一个更好的解释,关于TextEditingController的好处。

我的理解是onChanged的setState会通知所有小部件状态变量值的变化。这样,任何小部件(例如文本)都可以简单地使用状态变量,并且会收到有关其更改的通知。

我错误的希望是TextEditingController将使我甚至不需要状态变量变得更加简单。如下所示:

import "package:flutter/material.dart";

class TestForm extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return TestFormState();
  }
}

class TestFormState extends State<TestForm> {
  //string myStateVariable = "";
  final ctrl = TextEditingController();

  @override
  Widget build(BuildContext context) {

    var tf = TextField(
      controller: ctrl,
    );

    var t = Text("Current value: " + ctrl.text);  // <<<<<<<<<<< false hope! doesnt work!

    var x = Column(children: <Widget>[tf,t],);

    return MaterialApp(home: Material(child: Scaffold(
      appBar: AppBar(title: Text("Test Form"),),
      body: x,
    )));
  }
}

谁能解释为什么TextEditingController或类似的东西无法管理状态本身,并通知所有使用者状态改变?

谢谢。

2 个答案:

答案 0 :(得分:1)

那不是假的。您只是不同步设置状态而已。 onChanged所做的事情完全可以通过这种方法实现:

class _TestFormState extends State<TestForm> {
  TextEditingController controller;

  @override
  void initState() {
    controller = TextEditingController();
    controller.addListener(() {
      setState(() {});
    });
    super.initState();
  }

  @override
  void dispose() {
    controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.spaceAround,
      children: <Widget>[
        Text('Current Value: ${controller.text}'),
        TextField(
          controller: controller,
        ),
      ],
    );
  }
}

如您所见,每次控制器状态更改时,我们都有一个侦听器来设置状态。这正是onChanged的作用。

编辑:因此,关于收益,您可以通过两种方法实现所有目标,这是一种主观的方法。但是有些事情很重要:

1-如果您具有BLoC模式,则可以使用Stream方法直接分配onChanged

2-通过TextEditingController,您可以在许多地方使用同一控制器。您可以使用onChanged来达到相同的目的,但是当有人读取您的代码时,它看起来就像是变通方法,看起来像是破损的代码:)

3-onChanged方法对于RegEx断言等也非常可行。与控制器相比,它看起来要干净得多。

最后,我认为onChanged在大多数情况下对于模块化和更简洁的代码来说更好。正如我所说的,这完全取决于您,这一切我现在都可以想到。

答案 1 :(得分:1)

TextEditingController实际上是在管理自己的状态,因此,一旦更改输入,您就可以在屏幕上看到输入。

这里有2个问题,第一个问题是您没有向TextEditingController添加任何侦听器,您只是在构建窗口小部件时询问“给我当前值”,而不是“在任何时候给我值”变化”。为此,您需要向文本控制器添加一个侦听器,并且每次值更改时都会调用该侦听器。

尝试一下:

  @override
  void initState() {
    super.initState();
    // Start listening to changes.
    ctrl.addListener(_printValue);
  }

  _printValue() {
    print("Value: ${ctrl.text}");
  }

这将起作用,因为打印不需要在屏幕上呈现任何内容,但是如果将其更改为返回小部件,则也将无法工作。正如您所指出的,这是第二个问题,即在值更改时未重建父窗口小部件,在这种情况下,您无法避免在值更改时使用setState(或其他告诉flutter需要重建窗口小部件的方法),因为您需要重建窗口小部件以查看更改。

另一点我想指出的是TextEditingController功能强大,它可以用于将更改添加通知者的更多功能。例如,如果您想要屏幕其他部分上的按钮来清除TextField上的文本,则需要将TextEditingController绑定到该字段。

希望有帮助!