區分暫時性狀態與應用狀態
本文件介紹了應用狀態、暫時性狀態,以及如何在 Flutter 應用中管理它們。
從最廣泛的意義上講,應用的狀態是指應用執行時記憶體中存在的一切。這包括應用的資源、Flutter 框架維護的關於 UI 的所有變數、動畫狀態、紋理、字型等等。雖然這種最廣泛的狀態定義是有效的,但對於架構應用來說並不是很有用。
首先,有些狀態(如紋理)你甚至不需要管理。框架會為你處理這些。因此,一個更有用的狀態定義是“你在任何時刻重建 UI 所需的任何資料”。其次,你確實需要自己管理的狀態可以分為兩種概念型別:暫時性狀態和應用狀態。
暫時性狀態
#暫時性狀態(有時稱為*UI 狀態*或*區域性狀態*)是你可以在單個小部件中整齊地包含的狀態。
這是一個有意模糊的定義,以下是一些例子。
PageView中的當前頁面- 複雜動畫的當前進度
BottomNavigationBar中當前選中的選項卡
小部件樹的其他部分很少需要訪問這種狀態。它不需要序列化,也不會以複雜的方式改變。
換句話說,不需要對此類狀態使用狀態管理技術(ScopedModel、Redux 等)。你只需要一個 StatefulWidget。
下面,你將看到底部導航欄中當前選定的專案如何儲存在 _MyHomepageState 類的 _index 欄位中。在此示例中,_index 是暫時性狀態。
class MyHomepage extends StatefulWidget {
const MyHomepage({super.key});
@override
State<MyHomepage> createState() => _MyHomepageState();
}
class _MyHomepageState extends State<MyHomepage> {
int _index = 0;
@override
Widget build(BuildContext context) {
return BottomNavigationBar(
currentIndex: _index,
onTap: (newIndex) {
setState(() {
_index = newIndex;
});
},
// ... items ...
);
}
}在這裡,使用 setState() 和 StatefulWidget 的 State 類中的欄位是完全自然的。應用的其他任何部分都不需要訪問 _index。該變數只在 MyHomepage 小部件內部改變。而且,如果使用者關閉並重新啟動應用,你也不介意 _index 重置為零。
應用狀態
#不是暫時性的狀態,你希望在應用的許多部分共享,並希望在使用者會話之間保持,我們稱之為應用狀態(有時也稱為共享狀態)。
應用狀態的例子
- 使用者偏好設定
- 登入資訊
- 社交網路應用中的通知
- 電子商務應用中的購物車
- 新聞應用中文章的已讀/未讀狀態
為了管理應用狀態,你需要研究你的選擇。你的選擇取決於應用的複雜性和性質、團隊之前的經驗以及許多其他方面。請繼續閱讀。
沒有明確的規則
#需要明確的是,你*可以*使用 State 和 setState() 來管理應用中的所有狀態。事實上,Flutter 團隊在許多簡單的應用示例中(包括每次 flutter create 都會得到的起始應用)都是這樣做的。
反之亦然。例如,你可能會決定——在你的特定應用的上下文中——底部導航欄中選中的選項卡*不是*暫時性狀態。你可能需要從類外部改變它,在會話之間保持它,等等。在這種情況下,_index 變數就是應用狀態。
沒有一個明確的、普遍的規則來區分某個特定變數是暫時性狀態還是應用狀態。有時,你必須將一種狀態重構為另一種。例如,你可能從一些明顯的暫時性狀態開始,但隨著應用功能增長,它可能需要移動到應用狀態。
因此,對下圖要持保留態度。

當被問及 React 的 setState 與 Redux 的 store 時,Redux 的作者 Dan Abramov 回答道:
“經驗法則是:選擇最不麻煩的。”
總而言之,任何 Flutter 應用中都有兩種概念上的狀態型別。暫時性狀態可以使用 State 和 setState() 來實現,並且通常是單個小部件的區域性狀態。其餘的是你的應用狀態。這兩種型別在任何 Flutter 應用中都有其位置,兩者之間的劃分取決於你自己的偏好和應用的複雜性。