昨天我們討論了如何處理可預期的錯誤狀況,並針對不同情況,討論了幾種不同的處理方式。但是錯誤並非總是可以預期的,有些時候,我們的應用程式還是會發生一些不預期的狀況,例如:當 API 出現 Bug,回了一個不認識的 response,當我們的應用程式嘗試去解析 response 時,就會發生 json parse fail 的錯誤,又或者當網路斷線時,我們打任何 API 也都會得到網路不通的錯誤。
在開發 Flutter 的時候,我們可能需要處理幾種情況下發生的非預期錯誤:
聽起來好像我們需要處理很多事情,但其實 Flutter 已經為我們處理了,使用 Flutter 的 API,並帶入錯誤處理的方法。當錯誤發生時,App 不會停止運行,我們也能收到錯誤相關資訊。
如果開發過 Flutter 的讀者,可能曾經看過下面這個灰畫面的狀況。當我們沒有處理 Build 畫面時的錯誤,當 Build 畫面時失敗時,Flutter 不會讓程式停止運行,取而代之的是,在原本 Widget 該出現的地方,會出現這個灰畫面。
我們可以設定 ErrorWidget.builder,告訴 Flutter 當畫面出錯時,我們希望出現什麼 Widget,藉此,我們就可以替換一個符合當前 App 設計的錯誤畫面。同時,我們也要把錯誤回報到後台,讓我們可以知道使用者遇到了什麼問題。
https://dartpad.dev/?id=9c42a1505016b24a0e22c47a2b8e7534
若我們只是顯示錯誤畫面,那還不夠,我們還少做了一件事情:把錯誤回報給開發者。由於 App 是客端應用程式,當使用者發生錯誤時,有時候是錯在他的裝置上,開發者沒有任何機會知道使用者遇到了錯誤。所以,我們除了顯示錯誤畫面外外,還把錯誤回報給開發者。此時,我們必須把設定錯誤處理到 FlutterError.onError
同樣的,當非同步呼叫時出錯時,Flutter 也幫我們處理了錯誤,所以 App 並不會停止運行,畫面也不會出錯。但是如果有遇過這問題的讀者,可能會發現錯誤還是在 Console 中出現。我們並不希望錯誤只出現在 Console 中,因為這樣我們就不知道 Bug 的發生,所以必須像上一小節一樣,我們得把錯誤回報。
透過設定使用 runZoneGuard 來捕捉這些非同步的錯誤,並在相對應的 Callback 中回報錯誤。
https://dartpad.dev/?id=b4486b56d859177ed861784b5bc09862
當我們更新 Flutter 到 3.3 之後,我可以使用 PlatformDispatcher.instance.onError 來取代 runZoneGuard。
https://dartpad.dev/?id=b4486b56d859177ed861784b5bc09862
由於 Flutter 本身已經提供相對於完善的錯誤處理,對於如何處理非預期錯誤並不困難,我們只要正確認識如何使用 API,就能在保證 APP 穩定的同時,也能讓開發者發現錯誤,進而修復錯誤。