現在你已經學會了如何透過網路從伺服器載入資料,你的 Flutter 應用應該感覺更有活力了。然而,僅僅因為你“能夠”從遠端伺服器載入資料,並不意味著你總是“應該”這樣做。有時,最好重新渲染你從上一個網路請求中收到的資料,而不是重複請求並讓你的使用者再次等待其完成。這種保留應用資料以便將來再次顯示的技術被稱為“快取”,本頁面將介紹如何在 Flutter 應用中處理這項任務。

快取介紹

#

最基本地,所有快取策略都歸結為相同的三步操作,用以下偽程式碼表示:

dart
Data? _cachedData;

Future<Data> get data async {
    // Step 1: Check whether your cache already contains the desired data
    if (_cachedData == null) {
        // Step 2: Load the data if the cache was empty
        _cachedData = await _readData();
    }
    // Step 3: Return the value in the cache
    return _cachedData!;
}

有許多有趣的方式可以改變這種策略,包括快取的位置,你預先寫入值到快取或“預熱”快取的程度等等。

常見的快取術語

#

快取有其自身的術語,其中一些定義和解釋如下。

快取命中
當快取中已包含所需資訊,並且無需從真實的真相源載入時,稱之為快取命中。
快取未命中
當快取為空,並且所需資料從真實的真相源載入,然後儲存到快取中以備將來讀取時,稱之為快取未命中。

快取資料的風險

#

當真相源中的資料發生變化時,應用程式的快取被認為是“過期快取”,這使應用程式面臨呈現舊的、過時資訊的風險。

所有快取策略都存在持有陳舊資料的風險。不幸的是,驗證快取新鮮度的操作通常與完全載入相關資料所需的時間相同。這意味著大多數應用程式只有在信任資料在執行時無需驗證即可保持新鮮時,才能從資料快取中受益。

為了解決這個問題,大多數快取系統都為任何單個快取資料設定了時間限制。超過此時間限制後,潛在的快取命中將被視為快取未命中,直到載入新資料。

計算機科學家中流傳著一個流行的笑話:“計算機科學中最難的兩件事是快取失效、命名和差一錯誤。”😄

儘管存在風險,世界上幾乎所有應用程式都大量使用資料快取。本頁的其餘部分探討了在 Flutter 應用程式中快取資料的多種方法,但要知道所有這些方法都可以根據你的情況進行調整或組合。

在本地記憶體中快取資料

#

最簡單、效能最高的快取策略是記憶體快取。這種策略的缺點是,由於快取僅儲存在系統記憶體中,因此除了資料最初快取的會話之外,不會保留任何資料。(當然,這個“缺點”也有一個優點,那就是自動解決了大多數陳舊快取問題!)

由於其簡單性,記憶體快取與上面看到的虛擬碼非常相似。也就是說,最好使用經過驗證的設計原則,例如倉庫模式,來組織你的程式碼並防止上述快取檢查出現在你的整個程式碼庫中。

想象一個 UserRepository 類,它還負責在記憶體中快取使用者以避免重複的網路請求。它的實現可能如下所示:

dart
class UserRepository {
  UserRepository(this.api);
  
  final Api api;
  final Map<int, User?> _userCache = {};

  Future<User?> loadUser(int id) async {
    if (!_userCache.containsKey(id)) {
      final response = await api.get(id);
      if (response.statusCode == 200) {
        _userCache[id] = User.fromJson(response.body);
      } else {
        _userCache[id] = null;
      }
    }
    return _userCache[id];
  }
}

這個 UserRepository 遵循了多個經過驗證的設計原則,包括:

最棒的是,無論使用者在單個會話中訪問 Flutter 應用中載入給定使用者的頁面多少次,UserRepository 類都只會透過網路“一次”載入該資料。

然而,你的使用者最終可能會厭倦每次重新啟動應用時都等待資料載入。為此,你應該從下面列出的持久化快取策略中選擇一種。

永續性快取

#

在記憶體中快取資料永遠無法讓你的寶貴快取超越單個使用者會話。要享受應用首次啟動時快取命中帶來的效能優勢,你需要將資料快取到裝置的硬碟上。

使用 shared_preferences 快取資料

#

shared_preferences 是一個 Flutter 外掛,它封裝了 Flutter 所有六個目標平臺上特定於平臺的鍵值儲存。儘管這些底層平臺鍵值儲存是為小資料量設計的,但它們仍然適用於大多數應用程式的快取策略。有關完整指南,請參閱我們關於使用鍵值儲存的其他資源。

使用檔案系統快取資料

#

如果您的 Flutter 應用超出了 shared_preferences 理想的低吞吐量場景,您可能已準備好探索使用裝置檔案系統快取資料。有關更全面的指南,請參閱我們關於檔案系統快取的其他資源。

使用裝置上的資料庫快取資料

#

本地資料快取的終極解決方案是使用合適的資料庫讀寫資料的任何策略。存在多種型別,包括關係型和非關係型資料庫。所有方法都比簡單檔案顯著提高效能——特別是對於大型資料集。有關更全面的指南,請參閱以下資源:

快取圖片

#

影像快取與常規資料快取是一個類似的問題領域,但它有一個通用解決方案。要指示您的 Flutter 應用程式使用檔案系統儲存影像,請使用cached_network_image

狀態恢復

#

除了應用程式資料,你可能還想持久化使用者會話的其他方面,例如他們的導航堆疊、滾動位置,甚至填寫表單的部分進度。這種模式被稱為“狀態恢復”,並且是 Flutter 的內建功能。

狀態恢復的工作原理是,指示 Flutter 框架將其元素樹中的資料與 Flutter 引擎同步,然後引擎將其快取到特定於平臺的儲存中以供將來會話使用。要在 Android 和 iOS 的 Flutter 上啟用狀態恢復,請參閱以下文件:

反饋

#

由於本網站的這一部分正在不斷發展,我們歡迎您的反饋