Flutter 在验证表单时抛出错误

Posted

技术标签:

【中文标题】Flutter 在验证表单时抛出错误【英文标题】:Flutter throwing an error when validating form 【发布时间】:2021-09-22 22:40:32 【问题描述】:

这是它给我的错误 _formKey.currentState.validate : validate 收到错误 它要我使用空检查

方法'validate'不能被无条件调用,因为receiver可以是'null'。

final _formKey = GlobalKey<FormState>();

  moveToHome(BuildContext context) async
    if(_formKey.currentState.validate())
    
      setState(() 
        onLog = true;
      );
      await Future.delayed(Duration(milliseconds: 700));
      Navigator.pushNamed(context, MyRoutes.homeRoute);
      setState(() 
        onLog = false;
      );
    
  

它也给了我与验证器属性中的文本表单字段相同的功能

TextFormField(
                    decoration: const InputDecoration(
                      hintText: 'Enter username',
                      labelText: 'Username',
                    ),
                    onChanged: (value) 
                      uid = value;
                      setState(() );
                    ,
                    validator: (value) => value.isEmpty? 'Email cannot be empty' : null,
                  )

在验证器属性中 isEmpty 也建议使用空检查

我的整个代码清晰理解

class Login extends StatefulWidget 
  const Login(Key? key) : super(key: key);

  @override
  State<Login> createState() => _LoginState();


class _LoginState extends State<Login> 
  String uid = "";
  bool onLog = false;
  final _formKey = GlobalKey<FormState>();

  moveToHome(BuildContext context) async
    final f = _formKey.currentState;
    // if(f.validate())
    
      setState(() 
        onLog = true;
      );
      await Future.delayed(Duration(milliseconds: 700));
      Navigator.pushNamed(context, MyRoutes.homeRoute);
      setState(() 
        onLog = false;
      );
    
  

  @override
  Widget build(BuildContext context) 
    return Material(
      color: Colors.white,
      child: SingleChildScrollView(
        child: Form(
          key: _formKey,
            child: Column(
          children: [
            SizedBox(
              height: 20,
            ),
            Image.asset(
              'asset/image/welcome_logo.png',
              fit: BoxFit.cover,
            ),
            const SizedBox(
              height: 20,
            ),
            Text(
              'Hi, $uid',
              style: TextStyle(
                fontSize: 28,
                fontWeight: FontWeight.bold,
              ),
            ),
            Padding(
              padding: EdgeInsets.symmetric(vertical: 16, horizontal: 36),
              child: Column(
                children: [
                  TextFormField(
                    decoration: const InputDecoration(
                      hintText: 'Enter username',
                      labelText: 'Username',
                    ),
                    onChanged: (value) 
                      uid = value;
                      setState(() );
                    ,
                    validator: (value) => value == null ? 'Email cannot be empty' : null,
                  ),
                  const SizedBox(
                    height: 15,
                  ),
                  TextFormField(
                    obscureText: true,
                    decoration: const InputDecoration(
                        labelText: 'Password', hintText: 'Enter password'
                    ),
                    validator: (value) 
                      if(value == null)
                        return 'Please enter password!';
                      else if(value.length <6)
                        return 'password must be at least 6 characters';
                      
                      return value;
                    ,
                  ),
                  const SizedBox(
                    height: 30,
                  ),
                  InkWell(
                    onTap: () => moveToHome(context),
                    child: AnimatedContainer(
                      duration: Duration(milliseconds: 200),
                      width: onLog ? 50 : 150,
                      height: 50,
                      alignment: Alignment.center,
                      child: onLog
                          ? Icon(
                              Icons.done,
                              color: Colors.white,
                            )
                          : Text(
                              'Login',
                              style: TextStyle(
                                  fontWeight: FontWeight.bold, fontSize: 20),
                            ),
                      decoration: BoxDecoration(
                        color: Colors.cyan,
                        borderRadius: BorderRadius.circular(onLog ? 50 : 8),
                      ),
                    ),
                  )
                  // ElevatedButton(
                  //     onPressed: () =>
                  //       Navigator.pushNamed(context, MyRoutes.homeRoute),
                  //     ,
                  //     child: const Text('Login'),
                  //     style:TextButton.styleFrom(minimumSize: Size(140, 40)),
                  // )
                ],
              ),
            )
          ],
        )),
      ),
    );
  


 

【问题讨论】:

使用_formKey.currenState!.validate() 【参考方案1】:

关于 GlobalKey.currentState

来自GlobalKey.currentState 文档:

如果 (1) 树中没有与此全局键匹配的小部件,(2) 该小部件不是 [StatefulWidget],或者关联的 [State] 对象不是 @ 的子类型,则当前状态为 null 987654323@.

因此,如果您遵守这些条件(我无法从您分享的内容中推断出),您可以安全地使用 ! 运算符来忽略 GlobalKey 的可空性。

关于validator.value

这是因为TextFormField 固有的FormField 本身可以有一个空的初始值。但是,如果您查看 TextFormField 的实现永远不会为空(因为如果给出了 null,则默认值设置为 '')。因此在这里您可以安全地使用! 运算符。

一般的零安全

如果您在理解零安全概念本身时遇到困难,我建议您进行一些研究,因为这是一个庞大而强大的概念。您可以从这里开始:https://dart.dev/null-safety

【讨论】:

inside widget Form(key: _formKey),是的,它在一个有状态的 widget 中,但我不知道 T 的子类型是什么;我是 Flutter 的新手 我已经提交了我的完整代码 关于 GlobalKey,你已经准备好了,FormState 确实是应该提供给它的类。关于 validator.value 你读过我的答案了吗?检查 null 是否没有意义,您应该假设永远不会有 null 并检查它们是否为空(值!.isEmpty ?'电子邮件不能为空':null)。你也明白其中的意思吗!操作员?如果不是,我敦促您查看我提供的链接以了解 null 安全性。 哦,好的,它现在确实有效,当我使用 _formKey.currentState!.validate 时它首先给了我一个错误,现在它可以使用此代码工作。谢谢!!!

以上是关于Flutter 在验证表单时抛出错误的主要内容,如果未能解决你的问题,请参考以下文章

Flutter导航到新页面时抛出错误

Android Studio 在运行 Flutter App 时抛出异常

Flutter Stripe 在展示付款单时抛出 StripeException

我在 Flutter 中遇到了一个问题:在构建 TextField 时抛出了以下断言,它使我遇到了一个奇怪的问题

Laravel 验证在更新相同的唯一值时抛出错误

如何修复 Flutter 中的“解除绑定时抛出异常,java.lang.IllegalArgumentException:服务未注册:lp@9f7d4ca”异常? [复制]