You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Provider调用函数后TextField文本被清空,如何解决?

问题原因

你的代码中TextEditingController _controller = TextEditingController();是在build方法内部声明的。每次调用provider.changeErrorText()触发notifyListeners()时,Consumer会重建,进而触发build方法重新执行,新的TextEditingController实例会被创建,导致TextField丢失之前的输入内容。

解决方案

将TextEditingController的初始化移到build方法外部,确保它只被创建一次。推荐使用StatefulWidget来管理控制器的生命周期,这也是Flutter的最佳实践。

修改后的代码

TextFieldPage(改为StatefulWidget)

class TextFieldPage extends StatefulWidget {
  const TextFieldPage({super.key});

  @override
  State<TextFieldPage> createState() => _TextFieldPageState();
}

class _TextFieldPageState extends State<TextFieldPage> {
  // 将控制器声明为State类的成员变量,仅初始化一次
  final TextEditingController _controller = TextEditingController();

  @override
  void dispose() {
    // 页面销毁时销毁控制器,避免内存泄漏
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final provider = Provider.of<TextFieldProvider__>(context);

    return Scaffold(
      body: Column(children: [
        Consumer<TextFieldProvider__>(
          builder: (context, value, child) {
            return TextField(
              controller: _controller,
              decoration: InputDecoration(errorText: value.errorText),
            );
          },
        ),
        ElevatedButton(
          onPressed: () {
            if (_controller.text.isEmpty) {
              provider.changeErrorText('error');
            } else {
              provider.changeErrorText('');
            }
          },
          child: const Text("press"),
        )
      ]),
    );
  }
}

TextFieldProvider__(无需修改)

class TextFieldProvider__ extends ChangeNotifier {
  String _errorText = '';

  String get errorText => _errorText;

  void changeErrorText(String text) {
    _errorText = text;
    notifyListeners();
  }
}

额外说明

如果不想改为StatefulWidget,也可以将控制器声明为StatelessWidget的类成员变量:

class TextFieldPage extends StatelessWidget {
  const TextFieldPage({super.key});
  // 声明为类成员变量,确保仅初始化一次
  final TextEditingController _controller = TextEditingController();

  @override
  Widget build(BuildContext context) {
    // 其余代码不变
  }
}

但这种方式的局限性在于:如果TextFieldPage被父组件重新实例化,控制器会被重建,仍可能丢失输入内容。因此更推荐使用StatefulWidget的方案。

内容的提问来源于stack exchange,提问作者Saad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 04:15:45