由于 Dart 中的类型,该参数的值不能为 'null'

The parameter can't have a value of 'null' because of its type in Dart

飞镖函数

我有以下 Dart 函数,我现在正在使用空安全:

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

分析器抱怨:

The parameter 'factor' can't have a value of 'null' because of its type, and no non-null default value is provided.

Flutter 小部件

我的StatelessWidget在Flutter中也是这样:

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

  // ...
}

我收到以下错误:

The parameter 'key' can't have a value of 'null' because of its type, and no non-null default value is provided.


我该如何解决这个问题?

这是 Dart 添加不可空特性的主要原因。因为,您将 Key 传递给 super class,它可能是 null,所以您要确保它不为 null。您可以做的是根本不使用 key 或为其提供默认值或使其成为 required。喜欢:

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

或像这样要求key

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

为什么

发生这种情况的原因是因为启用了 空安全 ,您的 non-nullable 参数 factorkey 不能null.

在函数和构造函数中,这些值 可能 当函数在没有指定参数的情况下调用时 nullcalculate()Foo().然而,因为类型(intKey)是 non-nullable,所以这是 无效的 代码 - 他们绝不能为空。

解决方案

基本上有三种解决方法:

required

这可能是此问题最常见的解决方案,它表示必须设置变量 。这意味着如果我们有(注意 required 关键字):

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

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

默认值

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

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

现在,calculate() 调用将使用 42 作为 factor,这显然是 non-null。

可为空的参数

第三个解决方案是您真正要考虑的问题,即您是否想要一个可为空的参数?如果是这样,在您的函数中使用它时,您将必须对参数进行空检查。

但是,这是解决 Key key 问题最常见的方式,因为您并不总是希望在 Flutter 中为小部件提供密钥(请注意可为空的 Key? 类型):

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

  // ...
}

现在,您可以安全地构造 Foo() 而无需提供密钥。

位置参数

请注意,这同样适用于 positional 参数,即它们可以为空或 non-nullable,但是,它们不能用 required 和不能有默认值,因为它们总是需要才能传递。

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

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

作为先前 @creativecreatorormaybenot 回答的附加信息,您还可以使用 位置参数 (无大括号)默认情况下是强制性的,因此不可为空。

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

并且在没有命名参数的情况下被调用:

calculate(12);

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

class Foo extends StatelessWidget {
  final String myVar;

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

  // ...
}

" 后面可以跟命名参数,也可以跟可选的位置参数(但不能同时跟这两个)",请参阅此处的文档:dart parameters

关于命名参数和位置参数之间差异的有趣答案:What is the difference between named and positional parameters in 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,

如果我从 class 的 constructor 指向 key 得到这个错误,我添加一个 ' ?' 像这样在 Key 前面标记:

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

'?'表示可以是nullable

更改 pubspec 中的 sdk 版本

environment:
  sdk: ">=2.7.0 <3.0.0"