颤振:在有状态小部件中初始化"widget-dot"类级变量的后期 -- 这是怎么回事?



考虑有状态小部件的状态类中的以下类级属性:

int myInt = widget.int;

Android Studio 通知:"无法在初始值设定项中访问实例成员'小部件'。

(我明白这个错误意味着什么)。

因此,如果我们添加 late 关键字,它似乎很好:

late int myInt = widget.int;

然而。。。这让我感到惊讶的是,我被允许在一行中完成所有这些操作——我认为后期变量不必设置为空:

late int myInt;

。然后在 onInit 内部分配。

由于我没有声明何时分配它,因此我不知道何时进行分配。

问题是:

单行"late int myInt = widget.int;"是否完全等同于在 initState 方法中自己分配它?

Dart 中的late关键字有 2 种不同的用法,融合成一个关键字。


第一次使用,例如late int i

这种用法是众所周知的:延迟分配值,直到以后。这最常用于使字段不可为空,即使您可能没有立即获得该值。我相信你熟悉这种用法。

第二种用法,例如late int i = 0

这是为了延迟值计算,直到访问字段。当计算值的成本很高时,这很有用,因此您可能希望将其计算延迟到第一次需要它。官方文档中有说明:

执行此操作时,初始值设定项将变为延迟。而不是运行它 一旦实例被构造,它就会延迟并延迟运行 首次访问字段时。换句话说,它完全有效 就像顶级变量或静态字段上的初始值设定项一样。这可以 当初始化表达式成本高昂且可能不高时,请方便 需要。

所以基本上,取决于你是否立即分配一个值(在同一行上),Dart将决定你正在使用2种用法中的哪一种。如果你写late int i这将是第一次用法,如果你写late int i = 0late int i = calculateValue()这将是第二次用法:将计算延迟到第一次访问字段i。这就像 Kotlin 中的lateinit或 Swift 中的lazy

现在回到你的案例。通过在与late关键字相同的行上分配值,您将使用第二种用法,基本上是"lazy init",直到第一次访问该字段。在访问它时,此类将被实例化,因此(到那时)您可以使用this关键字。

在第一种情况下,Android studio会抛出该错误,因为int myInt声明时需要一个值。

在那个特定时刻,在 Statefull 小组件状态下,widget对象不可访问。

在第二种情况下:

late int myInt = widget.int;

这是变量的有效单行声明和赋值,但效果与onInit替代方案略有不同。

late关键字的工作方式lazy。 它不是在构建实例后立即运行,而是在第一次使用字段时运行。在那一刻,widget对象将可以访问。

看看这个问题的答案,它会有所帮助:这里

onInit内分配值可保证在初始化小部件时实际上只分配一次该值。

widget.xxx对应于小部件实例的xxx的值,即小部件一旦存在。

因此,当您在小部件初始化中使用widget.xxx时,varxxx不存在。

这就是为什么飞镖编译器告诉你The instance member 'widget' can't be accessed in an initializer.

通过在声明前面添加关键字,可以告诉编译器稍后将定义此变量。

但要小心,它实际上必须在以后定义(例如在 initState 中),并且在任何情况下都不需要在使用之前。

此错误来自这样一个事实,即 dart 现在是一种空安全感知语言。

也就是说,一种努力确保没有变量可以具有空值的语言。这是出于代码质量和更高的代码安全性的原因。

相关内容

  • 没有找到相关文章

最新更新