Dart/Flutter 个空安全问题

Dart/Flutter problems with null-safety

在不同的情况下,我在 Dart 中多次遇到空语句 (?) 的相同问题。我真的希望有人能帮助我。

刚刚添加了一些代码行和错误:

错误:

The property 'isEmpty' can't be unconditionally accessed because the receiver can be 'null'. Try making the access conditional (using '?.') or adding a null check to the target ('!'). here

这是我的例子之一:

child: MaterialButton(
                          onPressed: () {
                            var currentState = this._formKey.currentState;
                            if (currentState == null) {
                              return;
                            }
                            if (_formKey.currentState.validate()) {
                              AuthService.instance.signIn(
                                  email: emailTextEditingController.text,
                                  password:
                                      passwordTextEditingController.text);
                              if (AuthService.instance
                                      .checkIfUserExists() ==
                                  true) {
                                Navigator.pushReplacement(
                                    context,
                                    MaterialPageRoute(
                                        builder: (context) => MainMenu()));
                              } else {
                                Navigator.pushReplacement(
                                    context,
                                    MaterialPageRoute(
                                        builder: (context) =>
                                            VerifyScreen()));
                              }
                            }
                          },

再次收到此错误消息:

The method 'validate' can't be unconditionally invoked because the receiver can be 'null'.Try making the call conditional (using '?.') or adding a null check to the target ('!').

在我用 !避免像这样的空语句:

singUpUser() {
if (formKey.currentState!.validate()) {
  setState(() {
    isLoading = true;
  });
} else {
  return null;
};

但是现在我只是避免了代码本身的错误,在启动模拟器并测试它之后,出现了下一个错误:

Null check operator used on a null value

所以这不是正确的解决方案...

如果您需要更多代码,请给我发消息。

谢谢!

汤姆

为空与为空不同。因此,在检查对象是否为空之前,您需要先检查空值。

if (obj != null && !obj.isEmpty) {}

简而言之:如果 Dart 确定 一个变量在编译时可以在[=69时null =]时间,它不会编译.. 除非你明确检查空值,and/or使用!运算符将变量提升为不可空(Dart 在某些情况下并不总是能够推断出不可空性,因此我们有责任将它们提升为不可空性)。

如果您好奇(“为什么?”,对于初学者),还有很多要知道的,所以我建议 check the null safety documentation(快速阅读)。

也就是说,您的代码现在发生了变化:

(1) 在访问它之前,我们必须检查 val 是否可以为空。我们可以使用 !.? 来安全地访问它; 注意:空值检查运算符!最不安全的空值运算符,它很可能会导致运行时间例外。

validator: (val) {
  val==null || val?.isEmpty || val?.length<3
  ? "Enter Username 3+ characters"
  : null
}

(2)我自己无法推断哪个方法/变量可以为null

(3) 这取决于您要做什么,但我猜您正在尝试实施 Firebase 身份验证过程,您的用户 可以并且应该 在验证之前为空。因此,您的函数应该接受 nullable 用户值 (User?)。在那里,我们进行通常的 null 检查,并添加一个 ! 运算符以提升其值,以防 user 不是 null。如前所述,Dart 并不总是能够推断变量的可空性。

MyUser _userFromFirebaseUser(User? user) {
   return user==null ? null : MyUser(userId: user!.uid);
}

请注意,这里使用 null 检查 ! 是完全安全的,只是因为您刚刚在同一行中检查了它的可空性(尽管如此,重构时请保持明智的眼光)。

编辑。 (4) 我无法推断出你的异常到底在哪里被触发,但既然你想验证你的表单,那么这是我的一个项目中的代码:

// inside "saveForm()"...
var currentState = this._formKey.currentState;
if (currentState == null)
  return; // this just means something went wrong
if (!currentState.validate()) return; // todo if invalid, handle this, maybe show a snackbar and stuff...

请注意变量 currentState 现在如何使用 null 检查运算符 ! 提升为不可空的 WITHOUT,这是一个很好的做法(尽可能避免使用 !,最好使用空感知运算符,例如 ?.??,或 ?=)