區分臨時狀態和應用狀態
如何區分臨時狀態和應用狀態。
本文件介紹應用狀態、臨時狀態以及如何在 Flutter 應用中管理它們。
從最廣泛的意義上講,應用程式的狀態是指應用程式執行時記憶體中存在的所有內容。這包括應用程式的資源、Flutter 框架維護的所有關於 UI 的變數、動畫狀態、紋理、字型等等。雖然這種最廣泛的狀態定義是有效的,但它對於構建應用程式架構來說用處不大。
首先,你甚至不需要管理某些狀態(例如紋理)。框架會為你處理這些。因此,狀態的一個更有用的定義是“重建你的 UI 在任何時間點所需的所有資料”。其次,你自己管理的那些狀態可以分為兩種概念型別:臨時狀態和應用狀態。
臨時狀態
#臨時狀態(有時稱為UI 狀態或區域性狀態)是指可以整潔地包含在單個 Widget 中的狀態。
這,有意地,是一個模糊的定義,所以這裡有一些例子。
- 當前頁面在
PageView中 - 複雜動畫的當前進度
BottomNavigationBar中當前選定的標籤
Widget 樹的其他部分很少需要訪問這種狀態。不需要序列化它,並且它不會以複雜的方式改變。
換句話說,不需要對這種狀態使用狀態管理技術(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 Widget 內部改變。而且,如果使用者關閉並重新啟動應用程式,你不會介意 _index 重置為零。
應用狀態
#不是臨時狀態,你希望在應用程式的許多部分之間共享的狀態,並且你希望在使用者會話之間保留的狀態,我們稱之為應用程式狀態(有時也稱為共享狀態)。
應用程式狀態的例子
- 使用者偏好設定
- 登入資訊
- 社交網路應用程式中的通知
- 電子商務應用程式中的購物車
- 新聞應用程式中文章的已讀/未讀狀態
對於管理應用程式狀態,你需要研究你的選項。你的選擇取決於應用程式的複雜性和性質、你的團隊的先前經驗以及許多其他方面。請繼續閱讀。
沒有明確的規則
#明確地說,你可以使用 State 和 setState() 來管理應用程式中的所有狀態。事實上,Flutter 團隊在許多簡單的應用程式示例中都這樣做(包括你使用每個 flutter create 獲取的啟動應用程式)。
情況也相反。例如,你可能會決定——在你的特定應用程式的上下文中——底部導航欄中選定的標籤不是臨時狀態。你可能需要從類外部更改它,在會話之間保留它,等等。在這種情況下,_index 變數是應用程式狀態。
沒有明確的、普遍的規則來區分某個變數是臨時狀態還是應用程式狀態。有時,你必須將一個重構為另一個。例如,你將從一些明確的臨時狀態開始,但隨著你的應用程式在功能上增長,你可能需要將其移動到應用程式狀態。
因此,請帶著謹慎的態度看待以下圖表
當被問及 React 的 setState 與 Redux 的 store 時,Redux 的作者 Dan Abramov 回答說
"經驗法則:做任何不那麼尷尬的事情。"
總而言之,任何 Flutter 應用程式中都有兩種概念型別的狀態。臨時狀態可以使用 State 和 setState() 實現,並且通常是單個 Widget 的區域性狀態。其餘的是你的應用程式狀態。這兩種型別在任何 Flutter 應用程式中都有其用途,並且兩者之間的劃分取決於你自己的偏好和應用程式的複雜性。