Just My Life & My Work

Flutter 例外處理

透過 Flutter 框架開發的 App (含 iOS 與 Android) 已經上線,開始要追蹤用戶使用時,是否有發生不預期的狀況。

如同開發原生 iOS App 那樣,我將 Firebase Crashlytics 導入 Flutter App 中,一旦有任何崩潰、例外狀況,就會被記錄且上傳到 Firebase,讓我每天能明確掌握 App 使用狀況,並在適當時機修正並釋出新版本。🙃

這是我開啟記錄「例外」事件功能後,在 Firebase 上所搜集統計的資料。在沒有開啟此功能前是一片祥和,幾乎沒有「崩潰」事件。然而我為了優化 App 各種不預期的使用狀況,便有需要去了解會有哪些「例外」事件。🤔

開發 Flutter App 的過程有些狀況跟原生 App 不太一樣,其中一項是 Flutter App 比較不容易發生 Crash,至少在我開發時沒遇過閃退,反而會出現紅色黃字的錯誤畫面。

我好奇為何 Flutter App 不容易閃退,原來是因為 Flutter 程式語言 Dart 與原生程式語言.ObjectiveC (Swift)、Java (Kotlin) 的模型不一樣,使得程式運行中的崩潰與例外處理機制不同。

在介紹 Flutter 異常捕獲之前必須先了解 Dart 單線程模型,只有清楚了解 Dart 程式碼執行流程,我們才能知道該在哪裡去捕獲異常。

Dart單線程模型

在 Java 和 Objective-C 中,如果程式發生異常且沒有被捕獲,那麼程式將會終止,但是這在 Dart 或 JavaScript 中則不會!追究其原因,這和它們的運作機制有關係。Java 和 Objective-C 都是多執行緒模型的程式語言,任一個執行緒觸發異常且該異常未被捕獲時,就會導致整個程式退出。但 Dart 和 JavaScript 不會,它們都是單線程模型,運行機制很相似但有區別,我們可透過 Dart 官方提供的一張圖來看看 Dart 大致運行原理:

Dart 在單線程中是以訊息循環機制來運行的,其中包含兩個任務隊列,一個是「微任務隊列」 microtask queue,另一個叫做「事件隊列」event queue。從圖中可以發現,微任務佇列的執行優先權高於事件佇列

現在我們來介紹一下 Dart 執行緒運行過程,如上圖所示,入口函數 main() 執行完後,訊息循環機製便啟動了。首先會依照先進先出的順序逐一執行微任務佇列中的任務,事件任務執行完畢後程式便會退出,但是,在事件任務執行的過程中也可以插入新的微任務和事件任務,在這種情況下,整個執行緒的執行過程就是一直在循環,不會退出,而 Flutter 中,主執行緒的執行過程正是如此,永不終止。

在 Dart 中,所有的外部事件任務都在事件隊列中,如IO、計時器、點擊、以及繪製事件等,而微任務通常來自 Dart 內部,並且微任務非常少,之所以如此,是因為微任務佇列優先權高,如果微任務太多,執行時間總和就越久,事件佇列任務的延遲就越久,對圖形使用者介面應用來說最直覺的表現就是比較卡,所以必須確保微任務佇列不會太長。

在事件循環中,當某個任務發生異常並沒有被捕獲時,程式並不會退出,而直接導致的結果是當前任務的後續程式碼就不會被執行了也就是說一個任務中的異常是不會影響其他任務執行的。

Flutter 是一個開源的移動應用程式開發框架,具有許多內建的功能和機制,可以幫助應用程式在遇到異常情況時不崩潰。以下是一些讓 Flutter 應用程式不崩潰的原因:

  • Dart 語言:Flutter 使用 Dart 編程語言,Dart 具有先進的異常處理機制,可以讓開發者更容易地捕獲和處理異常。這意味著開發者可以在程式碼中添加 try-catch 塊,以捕獲可能引發異常的程式碼,並在遇到問題時採取適當的措施,而不是崩潰應用程式。
  • Widget 框架:Flutter 的 UI 構建是基於 Widget 概念的,這些小部件是不可變的並且具有自己的生命週期。當應用程式的某一部分遇到問題時,僅該部分會受到影響,不會導致整個應用程式崩潰。
  • Isolates 隔離:Flutter 使用 Dart 的 Isolate 機制來實現多線程,這允許應用程式在不同的線程中執行程式碼。如果一個 Isolate 遇到異常,其他 Isolates 可以繼續運行,不會影響整個應用程式。
  • Hot Reload 熱重載:Flutter 提供了熱重載功能,允許開發者在不重啟應用程式的情況下即時應用程式碼變更。這有助於快速修復錯誤,而不必重新啟動應用程式。
  • 錯誤處理:Flutter 提供了各種方式來捕獲和處理錯誤,包括異常處理、錯誤界面和報告機制。這些工具可以幫助開發者識別問題,向用戶提供有關錯誤的信息,同時保持應用程式的穩定性。

儘管 Flutter 具有這些特性,開發者仍然需要謹慎設計和測試應用程式,以確保它們在各種情況下都能夠正常運行,並優化性能以減少潛在的異常情況。

其中 Isolates 隔離較為不好理解,將會另起文章說明。😆

回到我當前主導的 App,若是原生 App 看到不受當機影響的使用者只有 22%,肯定會暴跳如雷,因為會認為用戶一直在崩潰中⋯⋯但事實上,不是 Crash,而是 Exception。

我看了下方列出的前三名例外事件,這將是我優化的首要目標。主要是帳號登入後的 Session 只有兩天時效,於是一旦超過時間,進行 API 呼叫就會出現例外事件。

接下來,就是持續優化 App 運行流程,無論是以用戶角度還是開發者角度。😌

參考:

隨意留個言吧:)~

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料

標籤雲