簡體   English   中英

Flutter:延遲初始化有狀態小部件中的“小部件點”類級變量——這是怎么回事?

[英]Flutter: Late Initializing a "widget-dot" Class-level Variable in a Stateful Widget -- What's Going on?

考慮有狀態小部件的 state class 內的以下 class 級別屬性:

int myInt = widget.int;

Android Studio 通知:“無法在初始化程序中訪問實例成員‘widget’。”

(我明白這個錯誤是什么意思)。

那么如果我們添加 late 關鍵字,它似乎沒問題:

late int myInt = widget.int;

然而......令我驚訝的是我被允許在一行中完成所有這些 - 我認為晚期變量必須不設置/設置為 null:

late int myInt;

...然后在 onInit 內部分配。

由於我沒有聲明何時分配它,所以我不知道分配何時發生。

問題是:

一行代碼是“late int myInt = widget.int;” 完全等同於在 initState 方法中自己賦值?

Dart 中的late關鍵字有兩種不同的用法,融合為一個關鍵字。


第一種用法,例如late int i

這種用法是眾所周知的:延遲分配一個值,直到以后。 這最常用於使字段不可為空,即使您可能不會立即獲得該值。 我相信您對這種用法很熟悉。

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

這是為了延遲值計算,直到訪問該字段。 這在值的計算成本很高時很有用,因此您可能希望將其計算延遲到第一次需要它時。 官方文檔上是這么寫的:

當你這樣做時,初始化器變得惰性。 它不是在構造實例后立即運行它,而是延遲並在第一次訪問該字段時延遲運行。 換句話說,它的工作方式與頂級變量或 static 字段上的初始值設定項完全相同。 當初始化表達式代價高昂並且可能不需要時,這會很方便。

所以基本上,取決於你是否立即分配一個值(在同一行),Dart 將決定你使用的是兩種用法中的哪一種。 如果你寫late int i會是第一次使用,如果你寫late int i = 0late int i = calculateValue()會是第二次使用:延遲計算直到字段i第一次被訪問時. 就像lateinit中的 lateinit 或 Swift 中的lazy

現在回到你的情況。 通過在與late關鍵字相同的行上分配一個值,您使用的是第二種用法,基本上是“惰性初始化”,直到第一次訪問該字段為止。 當它被訪問時,這個 class 已經被實例化,所以(到那個時候)你可以使用this關鍵字。

在第一種情況下 Android studio 會拋出該錯誤,因為int myInt在您聲明它時需要一個值。

在那個特定時刻,在 Statefull 小部件 state 中, widget object 不可訪問。

在第二種情況下:

late int myInt = widget.int;

這是有效的一行聲明和變量賦值,但效果與onInit替代方案有點不同。

late 關鍵字以lazy方式工作。 它不是在構建實例后立即運行,而是在第一次使用該字段時運行。 在那一刻, widget object 將可以訪問。

看看這個問題的答案,它會有所幫助: 這里

onInit內部分配值可確保在初始化小部件時僅實際分配一次值。

widget.xxx對應一個widget實例的xxx的值,即widget一旦存在。

因此,當您在小部件的初始化中使用widget.xxx時,var xxx不存在。

這就是為什么 dart 編譯器告訴您The instance member 'widget' can't be accessed in an initializer原因。

通過在聲明前添加關鍵字 late,您告訴編譯器該變量將在稍后定義。

但是要小心,它真的必須稍后定義(例如在 initState 中)並且在任何情況下都必須在使用之前定義。

這個錯誤是因為 dart 現在是 null 安全感知語言。

也就是說,一種努力確保沒有變量可以具有 null 值的語言。 這是出於代碼質量和更高代碼安全性的原因。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM