跳到主內容

區分臨時狀態和應用狀態

如何區分臨時狀態和應用狀態。

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

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

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

臨時狀態

#

臨時狀態(有時稱為UI 狀態區域性狀態)是指可以整潔地包含在單個 Widget 中的狀態。

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

  • 當前頁面在 PageView
  • 複雜動畫的當前進度
  • BottomNavigationBar 中當前選定的標籤

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

換句話說,不需要對這種狀態使用狀態管理技術(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 Widget 內部改變。而且,如果使用者關閉並重新啟動應用程式,你不會介意 _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() 實現,並且通常是單個 Widget 的區域性狀態。其餘的是你的應用程式狀態。這兩種型別在任何 Flutter 應用程式中都有其用途,並且兩者之間的劃分取決於你自己的偏好和應用程式的複雜性。