参数的值不能为‘ null’,因为它的类型是 Dart

飞镖功能

我有以下的 Dart 函数,我现在使用零安全:

void calculate({int factor}) {
// ...
}

分析师抱怨道:

由于类型的原因,参数“ factor”的值不能为“ null”,并且没有提供非 null 的默认值。

颤动小工具

这也是我的 StatelessWidget在扑动中的情况:

class Foo extends StatelessWidget {
const Foo({Key key}): super(key: key);


// ...
}

I get the following error:

参数‘ key’由于其类型不能具有‘ null’值,并且没有提供非 null 的默认值。


我该如何解决这个问题?

144751 次浏览

这也是为什么 Dart 增加了非空特性的主要原因。因为要将 Key传递给超类,它可能是 null,所以要确保它是非空的。您可以做的是要么根本不使用 key,要么为它提供一个默认值,要么将其设置为 required。比如:

MyPage({Key key = const Key("any_key")}) : super(key: key);

或按以下方式制作 key:

MyPage({required Key key}) : super(key: key);

Why

之所以会发生这种情况,是因为在 启用空安全中,不可取消参数 factorkey不能null

在函数和构造函数中,当没有命名参数 calculate()Foo()调用函数时,这些值 也许吧null。然而,因为类型(intKey)是 不可取消,这是 无效代码-他们绝不能是空。

解决方案

基本上有三种方法可以解决这个问题:

required

This is probably the most common solution to this problem and it indicates that a variable 必须设置. This means that if we have (notice the required keyword):

void calculate({required int factor}) {
// ...
}

我们指出,必须始终指定 factor参数,这解决了这个问题,因为只有 calculate(factor: 42)等将是函数的有效调用。

默认值

另一种解决方案是提供默认值。如果我们的参数有一个默认值,我们可以安全地不指定参数时调用的函数,因为默认值将使用:

void calculate({int factor = 42}) {
// ...
}

现在,calculate()调用将使用 42作为 factor,这显然是非空的。

可为空的参数

第三个解决方案是您真正想要考虑的问题,也就是说,您想要一个可为空的参数吗?如果是这样,那么在函数中使用该参数时,必须检查它是否为 null。

然而,这是你最常用的解决 Key key问题的方法,因为你并不总是想在 Flutter 中为你的小部件提供一个密钥(注意可以为空的 Key?类型) :

class Foo extends StatelessWidget {
const Foo({Key? key}): super(key: key);


// ...
}

现在,您可以在不提供密钥的情况下安全地构造 Foo()

位置参数

请注意,这同样适用于 位置参数,即它们可以为空或非空,但是,它们不能用 required注释,也不能有默认值,因为它们是要传递的 总是需要的

void foo(int param1) {} // bar(null) is invalid.


void bar(int? param1) {} // bar(null) is valid.

作为前一个 @ 创意创作者或者也许不是答案的附加信息,您还可以使用默认情况下必须使用的 positional parameters(没有花括号) ,因此不能为空。

  void calculate(int factor) {
// ...
}

并且调用时不命名参数:

calculate(12);

这些类型的参数可以这样用于构造函数:

class Foo extends StatelessWidget {
final String myVar;


const Foo(this.myVar, {Key? key}): super(key: key);


// ...
}

“可以后跟命名参数或可选的位置参数(但不能两者兼有)”,请看这里的医生: 省道参数

关于命名参数和位置参数之间差异的有趣答案: 在 Dart 中命名参数和位置参数的区别是什么?

为例子添加所需的函数

required Key key,
required this.id,
required this.name,
required this.code,
required this.img,
required this.price,
required this.promotionPrice,
required this.size,
required this.color,

如果我从指向 key的类的 constructor得到这个错误,我在 Key前面添加一个‘ ?’标记,如下所示:

const ClassName({Key? key}) : super(key: key);

?”表示可以是 nullable

在 pubspec 中更改 sdk 版本

environment:
sdk: ">=2.7.0 <3.0.0"

在 pubspec.yaml 中更改 SDK 版本可以解决以下问题:

环境: sdk: ">=2.1.0 <3.0.0"

在构造函数中的变量之前添加一个必需的关键字,并在 Key 旁边添加“ ?”。

  MyHomePage({Key? key, required this.title}) : super(key: key);