Flutter 有狀態跟無狀態

Stateful(有狀態) 和 stateless(無狀態) widgets

有些widgets是有狀態的, 有些是無狀態的
如果用戶與widget交互,widget會發生變化,那麽它就是有狀態的.
widget的狀態(state)是一些可以更改的值, 如一個slider滑動條的當前值或checkbox是否被選中.
widget的狀態保存在一個State對象中, 它和widget的布局顯示分離。
當widget狀態改變時, State 對象調用setState(), 告訴框架去重繪widget.
stateless widget 沒有內部狀態. Icon、 IconButton, 和Text 都是無狀態widget, 他們都是 StatelessWidget的子類。

stateful widget 是動態的. 用戶可以和其交互 (例如輸入一個表單、 或者移動一個slider滑塊),或者可以隨時間改變 (也許是數據改變導致的UI更新).Checkbox, Radio, Slider, InkWell, Form, and TextField 都是 stateful widgets, 他們都是 StatefulWidget的子類。

具有可變狀態的小部件

狀態是(1)可以在構建小部件時同步讀取的信息,以及(2)可能在小部件的生命週期內發生變化的信息。小部件實現者有責任使用 State.setState 確保在此類狀態更改時及時通知狀態。

有狀態小部件是通過構建更具體地描述用戶界面的其他小部件的星座來描述用戶界面的一部分的小部件。構建過程遞歸地繼續,直到用戶界面的描述完全具體。

當您描述的用戶界面部分可以動態更改時,有狀態小部件很有用,例如由於具有內部時鐘驅動狀態,或取決於某些系統狀態。對於僅依賴於對象本身的配置信息和小部件在其中膨脹的 BuildContext 的組合,請考慮使用 StatelessWidget。

StatefulWidget 實例本身是不可變的,並將其可變狀態存儲在由 createState 方法創建的單獨的 State 對像中,或者存儲在 State 訂閱的對像中,例如 Stream 或 ChangeNotifier 對象,其引用存儲在 StatefulWidget 的最終字段中本身。

每當它膨脹 StatefulWidget 時,框架都會調用 createState,這意味著如果該小部件已在多個位置插入到樹中,則多個 State 對象可能與同一個 StatefulWidget 相關聯。類似地,如果一個 StatefulWidget 從樹中移除,然後再次插入到樹中,框架將再次調用 createState 來創建一個新的 State 對象,從而簡化 State 對象的生命週期。

如果 StatefulWidget 的創建者使用 GlobalKey 作為其鍵,則 StatefulWidget 在從樹中的一個位置移動到另一個位置時會保持相同的 State 對象。因為具有 GlobalKey 的小部件最多可以在樹中的一個位置使用,所以使用 GlobalKey 的小部件最多有一個關聯元素。當通過將與該小部件關聯的(唯一)子樹從舊位置移植到新位置(而不是在新位置)。與 StatefulWidget 關聯的 State 對象與子樹的其餘部分一起被嫁接,這意味著 State 對像在新位置被重用(而不是重新創建)。但是,為了符合嫁接條件,小部件必須插入到與從舊位置移除的同一動畫幀中的新位置。

性能注意事項
StatefulWidget 有兩個主要類別。

第一個是在 State.initState 中分配資源並在 State.dispose 中處理它們,但它不依賴於 InheritedWidgets 或調用 State.setState。此類小部件通常用於應用程序或頁面的根目錄,並通過 ChangeNotifiers、Streams 或其他此類對象與子小部件進行通信。遵循這種模式的有狀態小部件相對便宜(就 CPU 和 GPU 週期而言),因為它們只構建一次就不會更新。因此,它們可以有一些複雜而深入的構建方法。

第二類是使用 State.setState 或依賴於 InheritedWidgets 的小部件。這些通常會在應用程序的生命週期內多次重建,因此盡量減少重建此類小部件的影響非常重要。 (他們也可能使用 State.initState 或 State.didChangeDependencies 並分配資源,但重要的部分是他們重建。)