问题描述
我正在尝试使自定义有状态小部件在颤振中工作。它称为 LetterTextForm,包含一些布局自定义和一个 TextField。
我希望可以轻松检索输入到小部件 TextField 中的文本,在小部件主体中使用某种 getter 方法返回 TextEditingController.text。问题是,当我使 TextEditingController 控制器成为这样的最终变量时:
class LetterTextForm extends StatefulWidget {
LetterTextForm({@required this.label,this.prefixIcon});
final Widget prefixIcon;
final String label;
final TextEditingController controller = TextEditingController();
String get textEntered => controller.text;
@override
_LetterTextFormState createState() => _LetterTextFormState();
}
class _LetterTextFormState extends State<LetterTextForm> {
@override
void initState() {
super.initState();
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return TextField(
controller: widget.controller,decoration: Inputdecoration(
prefixIcon: widget.prefixIcon,labelText: widget.label,)
);
}
}
抛出以下错误: “一个 TextEditingController 被处理后使用。”
我想问题可能在于控制器不应该是最终的,所以我将控制器移到了状态类中,并在状态类中创建了一个函数 textCallback,它修改了小部件中的非最终字符串班级。这种方式有效但违反了小部件不变性:
class LetterTextForm extends StatefulWidget {
LetterTextForm({@required this.label,this.prefixIcon});
final Widget prefixIcon;
final String label;
String text = '';
String get textEntered => text;
@override
_LetterTextFormState createState() => _LetterTextFormState();
}
class _LetterTextFormState extends State<LetterTextForm> {
var controller = TextEditingController();
void textCallback() {
widget.text = controller.text;
}
@override
void initState() {
super.initState();
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return TextField(
controller: controller,)
);
}
}
有没有一种方法可以做到 1) 不违反不变性和 2) 在用户按下 Enter 键时不立即处理 TextEditingController()?
当我摆脱 dispose() 方法时它会起作用,但似乎它可能会在以后导致一些性能/内存效率问题。也许我不知道我在说什么...
也许我应该尝试一些完全不同的东西,并将 TextEditingControllers 与 LetterTextForm 小部件的祖先一起放置在树中更远的位置,而不是在小部件内部?
解决方法
创建一个 ValueChanged<String>
回调成员,并在数据完成时回调。
class LetterTextForm{
...
final ValueChanged<String> onChanged;
...
}
class _LetterTextFormState extends ... {
final _controller = TextEditingController();
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(...) {
return TextField(
controller: _controller,onSubmitted: (value) {
if (widget.onChanged != null) {
widget.onChanged(value); // returns entered value to caller
}
},);
}
}
附言如果使用 TextFormField
则不需要控制器,您可以使用 initialData
进行初始化。