管理 Android 應用程式生命週期時,在背景資源回收期間保留使用者狀態,是提供流暢使用者體驗的核心要素。對於整合網頁工作流程的應用程式,WebView.saveState(Bundle) 可讓您將 WebView 的導覽記錄和狀態序列化為 Bundle。隨後可以使用 WebView.restoreState(Bundle) 還原這項資料。
不過,在瀏覽工作階段負載量較大的情況下,標準導入作業可能會遇到交易大小限制。本頁面說明這些架構限制,並提供相關策略,防止發生記憶體相關的例外狀況,同時保留瀏覽記錄。
1 MB 交易限制和狀態清除
Android 對可儲存在 savedInstanceState 中的資料總量設下嚴格的 1 MB 限制。這 1 MB 的預算會在整個應用程式程序中共用。如果應用程式包含多個 WebView 例項,這些例項的集合導覽狀態和記錄必須符合這個單一共用配置。超出這個界線會觸發 TransactionTooLargeException,導致應用程式當機。
常見但有問題的緩解策略包括監控 WebView 狀態套件的大小,並在超過任意安全門檻 (例如 300 KB) 時完全清除 WebView 記錄。雖然這樣可以避免當機,但會對使用者體驗造成嚴重影響:
無法返回上一個畫面:Android 通常會終止背景應用程式程序,以便回收記憶體供其他工作使用。您可以在
onSaveInstanceState()生命週期回呼中,使用saveState(Bundle)保留導覽記錄。如果清除這項記錄是為了避免達到 1MB 的交易限制,整個導覽堆疊就會遺失。使用者返回應用程式時,系統會立即透過返回按鈕離開元件或應用程式,因為無論是否重新啟動程序,系統都不會保留任何歷史記錄內容,以支援向後導覽。往返快取失效:清除記錄會導致應用程式無法使用往返快取 (BFCache),因此無法立即算繪先前造訪的網頁。
延遲時間增加:使用者會失去 WebView 中的目前狀態,必須重新導覽及重新初始化。這個程序會大幅增加網路負擔和交易延遲。
架構緩解策略
為避免 TransactionTooLargeException 崩潰,同時維持良好的使用者體驗,請在保留狀態和記憶體效率之間取得平衡。實作下列最佳化策略,即可安全地管理 1 MB 的交易預算,同時保留重要的瀏覽記錄和工作階段完整性。
強制執行狀態序列化的大小限制
導覽堆疊過大時,請勿完全清除,較有效率的做法是截斷歷來資料:
目標捨棄政策:使用
WebViewCompat.saveState()序列化狀態,同時強制執行特定位元組限制 (例如WebViewCompat.saveState(webView, outState, maxSizeBytes))。這項 API 會自動依序捨棄較舊的導覽項目,直到總酬載符合您定義的分配量為止。請注意,這項操作只會截斷序列化的Bundle,不會修改或清除有效WebView的即時記錄,確保立即返回導覽功能完全不受影響。移除轉送項目:如果應用程式介面提供返回按鈕,但缺少專用的下一頁導覽按鈕,您可以將
saveStateAPI 的includeForwardState參數設為false,捨棄所有轉送導覽項目。這樣做可大幅縮減有效負載大小,且不會影響使用者可用的導覽路徑。
使用 HTTP 快取配額 API 管理資源延遲
雖然 saveState 會管理暫時性導覽記錄的 1 MB Bundle 限制,但 HTTP Cache Quota API 可針對每個設定檔,手動控管持續性網頁資源 (磁碟快取)。這樣就能清楚區分短期導覽環境和長期快取資產。
選擇適當配額時,必須在效能方面做出取捨:
- 提高配額可將更多資產保留在磁碟上,進而改善離線可用性和資源載入延遲。
- 降低配額可減少應用程式占用的磁碟空間,並防止作業系統清除其他重要應用程式資料的快取。
這些設定會在應用程式重新啟動後保留,且必須從主要執行緒設定。
下列實作範例說明如何為預設設定檔設定磁碟快取配額:
Kotlin
if (WebViewFeature.isFeatureSupported(WebViewFeature.MULTI_PROFILE) &&
WebViewFeature.isFeatureSupported(WebViewFeature.HTTP_CACHE)) {
val defaultProfile = ProfileStore.getInstance()
.getOrCreateProfile(Profile.DEFAULT_PROFILE_NAME)
val httpCache = defaultProfile.httpCache
// Set explicit cache size to 50MB (50 * 1024 * 1024 bytes)
httpCache.setQuotaBytes(50L * 1024 * 1024)
}
Java
if (WebViewFeature.isFeatureSupported(WebViewFeature.MULTI_PROFILE) &&
WebViewFeature.isFeatureSupported(WebViewFeature.HTTP_CACHE)) {
Profile defaultProfile = ProfileStore.getInstance()
.getOrCreateProfile(Profile.DEFAULT_PROFILE_NAME);
HttpCache httpCache = defaultProfile.getHttpCache();
// Set explicit cache size to 50MB (50 * 1024 * 1024 bytes)
httpCache.setQuotaBytes(50L * 1024 * 1024);
}
如要進一步瞭解配額大小策略、生命週期管理和設定檔界限,請參閱「在 WebView 中管理 HTTP 快取配額」。
效能考量重點
以下幾點說明技術限制和內部資料行為,這些因素會影響 WebView 狀態行為:
不透明
PageStateBlob:saveState儲存的資料中,約有 70% 是來自算繪引擎的內部PageStateBlob。這項資料會擷取精細的會話狀態,包括表單輸入內容和 iframe 捲動位置。請勿嘗試從這些 Blob 手動剖析或剝除個別區段,因為這麼做會造成嚴重安全風險,並破壞工作階段還原完整性。精細的記錄管理:標準
WebBackForwardListAPI 不支援任意移除個別歷史元素。如要進行嚴格的狀態管理,您必須在WebViewCompat.saveState()中使用maxSizeBytes和includeForwardState參數實作截斷策略,確保架構安全。