我正在寻找关于 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 绑定到该字段。
希望能帮助到你!