在 Flutter 中声明一个没有初始化器的变量,具有空安全性

Declaring a variable with no initialiser in Flutter, with null safety

我正在尝试使用 Flutter 在我的应用程序中实施 Firebase 身份验证,并且我的编码最初工作正常,但自从我将项目迁移到 null safety 后,身份验证不再有效。我想我有 'isolated' 在那里。

例如,如果我们使用我的密码重置 TextField,就代码而言,这就是 TextField 的样子:

  TextField _buildEmailTextField() {
    return TextField(
      controller: _emailController,
      focusNode: _emailFocusNode,
      decoration: InputDecoration(
        labelText: 'Email',
        hintText: 'email@address.com',
        errorText: model.emailErrorText,
        enabled: model.isLoading == false,
      ),
      autocorrect: false,
      keyboardType: TextInputType.emailAddress,
      textInputAction: TextInputAction.done,
      onChanged: model.updateEmail,
      onEditingComplete: _submit,
    );
  }

当然,为了处理TextField的变化,你可以看到我添加了一个updateEmail函数onChanged: model.updateEmail。该函数本身如下所示:

void updateEmail(String email) => updateWith(email: email);

updateWith 函数如下所示:

  void updateWith({
    String email = '',
    bool isLoading = false,
    bool submitted = false,
  }) {
    this.email = email;
    this.isLoading = isLoading;
    this.submitted = submitted;
    notifyListeners();
  }

在空安全之前,我不需要用值初始化 updateWith 中的变量,所以它看起来像这样:

  void updateWith({
    String email,
    bool isLoading,
    bool submitted,
  }) {
    this.email = email;
    this.isLoading = isLoading;
    this.submitted = submitted;
    notifyListeners();
  }

来自 Firebase 的错误是:

[firebase_auth/missing-email] An email address must be provided

我认为这是由于我现在必须在 updateWith 中初始化 email 变量,并且我使用的是空字符串。因此,即使我在 TextField 中输入电子邮件,当我提交时,它也会提交空字符串,因此 Firebase 会告诉我我还没有提交电子邮件。我尝试过使用电子邮件作为可空值,如下所示:

  void updateWith({
    String? email,
    bool isLoading = false,
    bool submitted = false,
  }) {
    this.email = email!;
    this.isLoading = isLoading;
    this.submitted = submitted;
    notifyListeners();
  }

但是这给了我错误:

Null check operator used on a null value

既然我已经迁移到 null safety,我该如何使我的 updateWith 函数工作?正如我所说,它在空安全之前运行良好,所以我对逻辑很有信心。只是现在必须用函数内的变量初始化 email 意味着初始变量被提交给 firebase,而不是输入的电子邮件地址。有没有办法让这个工作,或者我可以重写我的 updateEmailupdateWith 函数,这样它们就不必用值初始化?

如果您需要我提供任何其他信息,我很乐意提供。谢谢指教!

改变void updateEmail(String email) => updateWith(email: email);

void updateEmail(String? email) => updateWith(email: email);

该方法对于 Dart/Flutter 开发人员来说非常不直观,除非您使用通用模式来实现。像这样的方法中那些可选参数的要点通常是只传递其中的几个,其余的保持不变。因此,例如,您可以仅调用 updateWith(email: 'test@example.com')email 将更新,但 isLoadingsubmitted 将保持不变。你只能在参数可以为空的情况下实现这一点,所以你有一个 marker/value 可以检查“根本没有设置”。

例如:

void updateWith({
    String? email,
    bool? isLoading,
    bool? submitted,
  }) {
    this.email = email ?? this.email;
    this.isLoading = isLoading ?? this.isLoading;
    this.submitted = submitted ?? this.submitted;

    notifyListeners();
  }

如果 email 是必需的参数,而其他两个无论如何都会设置为默认值,那么您根本不需要命名参数。只需将其设为具有正常位置参数的正常方法即可。

空安全并不意味着从不使用 null。如果某些东西在 null-safety 之前工作,它仍然可以通过使用可空类型在之后工作。

updateWithcopyWith 等函数通常旨在 仅使用 提供的参数,其余的不用理会。因此,这通常意味着使参数可为空:

 void updateWith({
    String? email,
    bool? isLoading,
    bool? submitted,
  }) {
    this.email = email ?? this.email;
    this.isLoading = isLoading ?? this.isLoading;
    this.submitted = submitted ?? this.submitted;
    notifyListeners();
  }

(请注意,如果调用者未提供 updateWith 的原始实现并没有这样做,并且无条件地使用 null 破坏字段。如果这实际上是您想要的行为,那么函数名称用词不当。)