【问题标题】:Still problems with async validations in flutter颤振中的异步验证仍然存在问题
【发布时间】:2019-10-17 15:22:06
【问题描述】:

我喜欢检查我的后端数据库中是否已经存在电子邮件。因此,我尝试使用在异步调用返回后应该更改的状态变量。我找到了以下包含已接受答案的线程。

Flutter - Async Validator of TextFormField

Flutter firebase validation of form field inputs

我尝试了这些答案以及一些变体,但它仍然对我不起作用。我只是模拟后端调用。打印设置 _emailExist 为 true,但我没有看到任何错误。如果我单击该按钮两次,则错误消息将正确显示。

import 'package:flutter/material.dart';

class LoginPage extends StatefulWidget {
  LoginPage({Key key}) : super(key: key);

  @override
  _LoginPageState createState() => _LoginPageState();
}

class _LoginPageState extends State<LoginPage> {
  final GlobalKey<FormState> _loginFormKey = GlobalKey<FormState>();
  bool _emailExist = false;

  @override
  initState() {
    super.initState();
  }

  checkEmail(String name) {

    // Simulare async call
    Future.delayed(Duration(seconds: 2)).then((val) {
      setState(() {
        _emailExist = true;
      });
      print(_emailExist);
    });
    return _emailExist;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text("Test"),
        ),
        body: Container(
            child: SingleChildScrollView(
                child: Form(
          key: _loginFormKey,
          child: Column(
            children: <Widget>[
              TextFormField(
                validator: (value) =>
                checkEmail(value) ? "Email already taken" : null,
              ),
              RaisedButton(
                child: Text("Login"),
                onPressed: () {
                  if (_loginFormKey.currentState.validate()) {}
                },
              )
            ],
          ),
        ))));
  }
}

【问题讨论】:

    标签: flutter dart


    【解决方案1】:

    TextFormField 需要一个同步函数作为验证器(这是一个执行某些任务然后返回其结果的普通函数。

    checkEmail 就是这个,一个同步函数。它设置了一个Future,它将在两秒钟内将_emailExist 设置为true。但至关重要的是,它不会等待两秒钟。它立即返回 _emailExist 的当前值(这是false 第一次运行时)。两秒钟后,您的Future 解析并将_emailExist 设置为true。这就是为什么当您第二次运行它时,它会按预期工作(_checkEmail 再次返回 _emailExist 的当前值,但现在是 true)。

    解决此问题的一种方法是提供onChangeddecoration 参数以达到相同的效果:

    TextFormField(
      onChanged: _handleChange,
      decoration: InputDecoration(
        errorText: _emailExist ? "Email already taken" : null,
      ),
    ),
    

    现在,您可以在文本字段更改时进行异步后端调用,然后根据响应更新状态:

    void _handleChange(String val) {
      Future.delayed(Duration(seconds: 2)).then(() {
        setState(() {
          _emailExist = true;
        });
        print(_emailExist);
      });
    }
    

    debounce 这个函数是个好主意,这样您就不会在用户输入的每个字母中都发送请求!

    这是一个很好的 video 和一些 docs 在 Flutter/Dart 中的异步编码。

    【讨论】:

      猜你喜欢
      • 2020-03-07
      • 2018-11-28
      • 2020-06-06
      • 2021-05-10
      • 2021-03-22
      • 2021-06-30
      • 1970-01-01
      • 2021-06-14
      • 2020-09-01
      相关资源
      最近更新 更多