如何在 Flutter 中将 textEditiing 控制器与 Provider 一起使用

Posted

技术标签:

【中文标题】如何在 Flutter 中将 textEditiing 控制器与 Provider 一起使用【英文标题】:How to use textEditiing controller with Provider in Flutter 【发布时间】:2020-09-03 21:00:50 【问题描述】:

我正在使用提供程序进行状态管理。我的表单中有多种类型的字段。问题在于文本字段 每当我更改 Text 时,它的行为就会很奇怪,就像输入的文本以相反的顺序显示一样。

class MyProvider with ChangeNotifier
  String _name;
  String get name => _name;
  setname(String name) 
    _name = name;
    notifyListeners();
  


class MyWidget extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    final MyProvider myProvider = Provider.of<MyProvider>(context);

    final TextEditingController _nameController = TextEditingController(
        text: myProvider.name,
    );

    return TextField(
        controller: _nameController,
        onChanged: myProvider.setname,
    );


【问题讨论】:

先生。你的代码对我来说很完美。在我看来,这是使用提供程序的 TextEditingController 的最佳解决方案。问题是您的提供商在您每次键入时都在听。你所需要的只是听:假的。 final MyProvider myProvider = Provider.of&lt;MyProvider&gt;(context, listen: false); 【参考方案1】:

这是因为 TextEditingController 的新实例在每个小部件构建时创建,并且有关当前光标位置 (TextEditingValue) 的信息丢失了。

initState 方法中创建一次控制器,并在dispose 方法中处理它。


class MyWidget extends StatefulWidget 
  @override
  _MyWidgetState createState() => _MyWidgetState();


class _MyWidgetState extends State<MyWidget> 
  TextEditingController _nameController;

  @override
  void initState() 
    final MyProvider myProvider = Provider.of<MyProvider>(context, listen: false);

    super.initState();
    _nameController = TextEditingController(text: myProvider.name);
  

  @override
  void dispose() 
    _nameController.dispose();
    super.dispose();
  

  @override
  Widget build(BuildContext context) 
    final MyProvider myProvider = Provider.of<MyProvider>(context);

    return TextField(
        controller: _nameController,
        onChanged: myProvider.setname,
    );
  

【讨论】:

这个方法有效,谢谢。我听说在使用提供程序时,我们可以避免使用有状态小部件并将其替换为无状态小部件,但这里我们使用的是有状态小部件。这不正确吗? @vinayakbhanushali TextEditingController 是视图(小部件)的一部分,仅在视图存在时才存在。虽然小部件存在,但控制器维护它并且必须存储在某个地方。当一个小部件被释放时,控制器也应该被释放。所以最好将控制器存储在它的小部件附近——在它的 state 中可以将它保存在 Provider 中,但这不是最佳实践,因为控制器与业务逻辑无关。但是,在 Provider 的帮助下,与业务逻辑相关的所有内容都从小部件的 State 转移到了 Provider。【参考方案2】:

要将文本字段中的文本存储到提供程序中,您需要将文本属性从控制器发送到提供程序:

_nameController.addListener(() 
    myProvider.setName(_nameController.text);
);

这也将消除您在 TextField 中获取反向文本的问题

【讨论】:

为了使用它,您还需要将小部件从 Stateless 更改为 Statefull 小部件 好的,这个方法也有效。你能告诉我哪种方法是你最正确的方法还是@igor-kharakhordin 的方法? @vinayakbhanushali 如果你给控制器添加一个监听器,它会在每个事件上被调用,包括光标位置的改变,文本选择等。最好使用TextFieldonChanged参数,只需就像你一样。我不确定这如何解决您的问题。

以上是关于如何在 Flutter 中将 textEditiing 控制器与 Provider 一起使用的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Flutter 中将 AlertDialog FlatButton 居中

如何在 Flutter 中将地图列表显示到 DropdownMenuItem 中

如何在flutter中将数据从firestore传递给Typeahead

如何在 Flutter 中将文本小部件彼此相邻包装

如何在 Flutter 中将 XFile 转换为文件

如何在 Flutter 中将 TextEditingController 转换为 String?