TextEditingController 与 OnChanged

S2L*_*S2L 23 dart flutter

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

我的理解是 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,
    )));
  }
}
Run Code Online (Sandbox Code Playgroud)

谁能解释为什么 TextEditingController 或类似的东西不能管理状态本身并通知所有消费者状态的变化?

谢谢。

Ese*_*met 15

那不是假的。您只是没有同步设置状态而已。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,
        ),
      ],
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

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

编辑:所以,关于好处,你可以用这两种方法实现一切,这是一种主观的方式。但有些事情很重要:

1 - 如果你有 BLoC 模式,你可以直接分配你的StreamwithonChanged方法。

2 -TextEditingController您可以在许多地方使用相同的控制器。你可以onChanged用更多的开销来实现同样的事情。

3 -onChanged方法对于 RegEx 断言等也非常可行。与控制器相比,它看起来会更清晰。

最后在我看来,onChanged在大多数情况下,模块化和更清晰的代码更好。正如我所说,这取决于你。


小智 8

TextEditingController 实际上是在管理他自己的状态,这就是为什么一旦你改变它就可以在屏幕上看到输入。

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

尝试这个 :

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

  _printValue() {
    print("Value: ${ctrl.text}");
  }
Run Code Online (Sandbox Code Playgroud)

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

另一件我想指出的事情是 TextEditingController 非常强大,它可以用于更多的事情,只需将通知程序添加到更改中即可。例如,如果您想要屏幕其他部分的按钮清除 TextField 上的文本,则需要将 TextEditingController 绑定到该字段。

希望能帮助到你!