简体   繁体   English

每当在 TextFormField Flutter 中触发验证 function 时,如何重建小部件?

[英]How to rebuild a widget whenever the validation function is triggered in TextFormField Flutter?

I'm receiving the following error message:我收到以下错误消息:

══╡ EXCEPTION CAUGHT BY FOUNDATION LIBRARY ╞════════════════════════════════════════════════════════ The following assertion was thrown while dispatching notifications for ErrorTextNotifier: setState() or markNeedsBuild() called during build. ══╡基金会图书馆捕获的例外╞═════════════════════════════════════════ ═══════════════ 在为 ErrorTextNotifier 调度通知时抛出以下断言:在构建期间调用了 setState() 或 markNeedsBuild()。 This _InheritedProviderScope<ValidityNotifier?> widget cannot be marked as needing to build because the framework is already in the process of building widgets.此 _InheritedProviderScope<ValidityNotifier?> 小部件无法标记为需要构建,因为框架已经在构建小部件的过程中。 A widget can be marked as needing to be built during the build phase only if one of its ancestors is currently building.仅当其祖先之一当前正在构建时,才可以在构建阶段将小部件标记为需要构建。 This exception is allowed because the framework builds parent widgets before children, which means a dirty descendant will always be built.这个例外是允许的,因为框架在子部件之前构建父部件,这意味着总是会构建一个脏的后代部件。 Otherwise, the framework might not visit this widget during this build phase.否则,框架可能不会在此构建阶段访问此小部件。 The widget on which setState() or markNeedsBuild() was called was: _InheritedProviderScope<ValidityNotifier?> The widget which was currently being built when the offending call was made was: This is my code (I've had to omit a bunch of the code) TextFormField调用 setState() 或 markNeedsBuild() 的小部件是:_InheritedProviderScope<ValidityNotifier?> 进行违规调用时当前正在构建的小部件是:这是我的代码(我不得不省略一堆代码)TextFormField


 @override
 Widget build(BuildContext context) {
   return ChangeNotifierProvider(
     create: (_) => ValidityNotifier(),
     child: Builder(builder: (context) {
       return Column(
         children: [
           TextFormField(
             autovalidateMode: AutovalidateMode.onUserInteraction,
             validator: (str) {
               var validity = //custom validity function
               Provider.of<ValidityNotifier>(context, listen: false).setValidity(validity);
               return null;
             },
           ),
           Consumer<ValidityNotifier>(builder: (context, model, child) {
             if (model.isValid) {
               return Text("Custom Validity Message")
             }
             return const SizedBox.shrink();
           }),
         ],
       );
     }),
   );
 }
}

class ValidityNotifier extends ChangeNotifier {
 bool _isValid = false;

 bool get isValid => _isValid;

 void setValidity(bool isValid) {
   _isValid=isValid;
   notifyListeners();
 }
}

I want the state to be changed every time the validation function is called, I've considered adding a listener to a TextEditingController but it would trigger a rebuild every time an input is made.我希望每次调用验证 function 时更改 state,我考虑过向 TextEditingController 添加一个侦听器,但每次输入时都会触发重建。

As the error message says you have concurrent builds running.正如错误消息所说,您正在运行并发构建。 When you call setValidity which triggers a rebuild due to notifyListeners , Flutter is already in the process of building the TextFormField .当您调用setValidity由于notifyListeners而触发重建时, Flutter 已经在构建TextFormField的过程中。

You can use a post frame callback , in this case the setValidity method call will run only once the current build is finished.您可以使用后帧回调,在这种情况下, setValidity方法调用将仅在当前构建完成后运行。

Instead of:代替:

Provider.of<ValidityNotifier>(context, listen: false).setValidity(validity);

Try this:尝试这个:

WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
  Provider.of<ValidityNotifier>(context, listen: false)
      .setValidity(validity);
});

Inside TextFormField TextFormField 内部

autovalidateMode: AutovalidateMode.onUserInteraction,
validator: (value) => value!.isEmpty ? "Your special string here" : null

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM