本文件介紹了應用狀態、暫時性狀態,以及如何在 Flutter 應用中管理它們。

從最廣泛的意義上講,應用的狀態是指應用執行時記憶體中存在的一切。這包括應用的資源、Flutter 框架維護的關於 UI 的所有變數、動畫狀態、紋理、字型等等。雖然這種最廣泛的狀態定義是有效的,但對於架構應用來說並不是很有用。

首先,有些狀態(如紋理)你甚至不需要管理。框架會為你處理這些。因此,一個更有用的狀態定義是“你在任何時刻重建 UI 所需的任何資料”。其次,你確實需要自己管理的狀態可以分為兩種概念型別:暫時性狀態和應用狀態。

暫時性狀態

#

暫時性狀態(有時稱為*UI 狀態*或*區域性狀態*)是你可以在單個小部件中整齊地包含的狀態。

這是一個有意模糊的定義,以下是一些例子。

  • PageView 中的當前頁面
  • 複雜動畫的當前進度
  • BottomNavigationBar 中當前選中的選項卡

小部件樹的其他部分很少需要訪問這種狀態。它不需要序列化,也不會以複雜的方式改變。

換句話說,不需要對此類狀態使用狀態管理技術(ScopedModel、Redux 等)。你只需要一個 StatefulWidget

下面,你將看到底部導航欄中當前選定的專案如何儲存在 _MyHomepageState 類的 _index 欄位中。在此示例中,_index 是暫時性狀態。

dart
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 重置為零。

應用狀態

#

不是暫時性的狀態,你希望在應用的許多部分共享,並希望在使用者會話之間保持,我們稱之為應用狀態(有時也稱為共享狀態)。

應用狀態的例子

  • 使用者偏好設定
  • 登入資訊
  • 社交網路應用中的通知
  • 電子商務應用中的購物車
  • 新聞應用中文章的已讀/未讀狀態

為了管理應用狀態,你需要研究你的選擇。你的選擇取決於應用的複雜性和性質、團隊之前的經驗以及許多其他方面。請繼續閱讀。

沒有明確的規則

#

需要明確的是,你*可以*使用 StatesetState() 來管理應用中的所有狀態。事實上,Flutter 團隊在許多簡單的應用示例中(包括每次 flutter create 都會得到的起始應用)都是這樣做的。

反之亦然。例如,你可能會決定——在你的特定應用的上下文中——底部導航欄中選中的選項卡*不是*暫時性狀態。你可能需要從類外部改變它,在會話之間保持它,等等。在這種情況下,_index 變數就是應用狀態。

沒有一個明確的、普遍的規則來區分某個特定變數是暫時性狀態還是應用狀態。有時,你必須將一種狀態重構為另一種。例如,你可能從一些明顯的暫時性狀態開始,但隨著應用功能增長,它可能需要移動到應用狀態。

因此,對下圖要持保留態度。

A flow chart. Start with 'Data'. 'Who needs it?'. Three options: 'Most widgets', 'Some widgets' and 'Single widget'. The first two options both lead to 'App state'. The 'Single widget' option leads to 'Ephemeral state'.

當被問及 React 的 setState 與 Redux 的 store 時,Redux 的作者 Dan Abramov 回答道:

“經驗法則是:選擇最不麻煩的。”

總而言之,任何 Flutter 應用中都有兩種概念上的狀態型別。暫時性狀態可以使用 StatesetState() 來實現,並且通常是單個小部件的區域性狀態。其餘的是你的應用狀態。這兩種型別在任何 Flutter 應用中都有其位置,兩者之間的劃分取決於你自己的偏好和應用的複雜性。