相对于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或类似的东西无法管理状态本身,并通知所有使用者状态改变?
谢谢。
答案 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绑定到该字段。
希望有帮助!