跳至主要內容

區分暫時性狀態和應用程式狀態

本文介紹應用程式狀態、暫時性狀態,以及如何在 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 應用程式中都有其作用,而兩者之間的劃分取決於您自己的偏好和應用程式的複雜性。