[譯] 使用 Catcher 處理 Flutter 錯誤
https://medium.com/flutter-community/handling-flutter-errors-with-catcher-efce74397862
作者:
Jakub Homlala
本圖片源自Unsplash 的Chor Hung Tsang
錯誤處理是程式設計師每天的工作,這事兒在日常工作中是沒完沒了的。在 Dart 語言中,我們可以用 try-catch 語言結構輕鬆地處理錯誤。但是,如果我們忘了寫 try-catch 程式碼會怎樣?我們會得到一個像下面這樣的“紅屏錯誤頁面”。
是的,我們的程式碼不都總是執行良好。每一個開發者都會有疏忽。但好的開發者會解決他所犯的失誤。
對使用者來說,一個重要的事情是,當我們是一個 APP 的使用者的時候,我們需要知道一些超出預期的事發生了,並且我們可以決定是否傳送錯誤日誌給開發者。錯誤日誌會幫助開發者修復錯誤。
開發者能修復錯誤,但他們需要知道發生了什麼錯誤和在哪兒發生的錯誤。在移動應用開發中,我們需要一個可以報告程式異常行為給開發者的工具。目前,在 Flutter 中我們已經支援了 Sentry 錯誤追蹤功能,很快也會支援 Firebase 的 Crashlytics。但是,如果我們不想使用 Sentry 或 Crashlytics 怎麼辦呢?如果我們使用一些配置簡單,還可以在開發階段甚至在已釋出後捕獲錯誤的通用的工具,那該怎麼實現呢?這個工具包含傳送郵件的功能,使用者只需點選“傳送” 就可以把錯誤反饋給開發者,或者把崩潰日誌儲存到裝置的儲存器中。這就是接下來將要介紹的 Catcher 了。
Catcher 簡介
Catcher 的 logo
Catcher 是一個新的捕獲和處理錯誤資訊的 Flutter 外掛。Catcher 提供多種錯誤報告模型和處理程式,以配合 Flutter 應用程式。Catcher 深受 ACRA 的啟發。
Catcher 報告流程是很容易理解的(參看下圖)。Catcher 將錯誤處理程式注入到你的應用程式中,從而可以捕獲所有未經檢測的錯誤。一旦它捕獲到錯誤,他就建立報告並將其傳送到reporter 中。reporter 顯示錯誤的相關資訊並等待使用者決策。如果使用者接受報告錯誤,則處理程式(handlers)將處理該報告。
你也可以報告你在 try catch 中檢查到的錯誤。
Catcher 也會收集使用者裝置硬體和作業系統的資訊。這些資料的獲取是可以不經使用者任何形式的授權,因為它不含有使用者的個人資訊。這些資料是很有幫助的,因為有些時候產生錯誤是因為裝置的問題而不是開發者的問題。
Catcher 原理圖
如何使用 Catcher
讓我們看一個使用 Catcher 的基本例子。首先我們需要安裝外掛。到你的 pubspec.yaml
檔案中加上下面內容:
dependencies: catcher: ^0.0.8複製程式碼
然後,你需要執行 packages get 命令下載和安裝到你的專案中。
最後一步是加上這一句 import:
import ‘package:catcher/catcher_plugin.dart';複製程式碼
我們已經準備好使用 Catcher了,下面就是使用 Catcher 的基本例子。
main() { //debug configurationCatcherOptions debugOptions = CatcherOptions(DialogReportMode(), [ConsoleHandler()]); //release configuration CatcherOptions releaseOptions = CatcherOptions(DialogReportMode(), [ EmailManualHandler(["[email protected]"])]); //profile configuration CatcherOptions profileOptions = CatcherOptions( NotificationReportMode(), [ConsoleHandler(), ToastHandler()], handlerTimeout: 10000, customParameters: {"example": "example_parameter"}, ); //MyApp is root widget Catcher(MyApp(), debugConfig: debugOptions, releaseConfig: releaseOptions, profileConfig: profileOptions); }複製程式碼
通常情況下,當你執行你的程式碼,你的 main 函式只有這一行: runApp(MyApp());
,這一行程式碼用來啟動應用。當你使用 Catcher 的時候,你將不再使用這一行程式碼。替代上面的方式,你需要用根 Widget 和 應用配置建立 Catcher 例項。
Catcher 允許你同時設定 3 種配置: debug
, release
和 profile
。在上面的程式碼中,我們建立了 3 個 CatcherOptions 例項,分別描述 Catcher 在不同模式下的行為方式。當應用執行在 debug 環境時,Catcher 會使用 debugConfig
,當應用執行在釋出環境時會使用 releaseConfig
當執行在 “profile” 模式時,會使用 profileConfig
。
在每一個 CatcherOptions
例項中,你可以配置不同的 報告模型和處理程式列表。 點選這裡 可以檢視 CatcherOptions
的所有的配置引數。
有 4 種報告模式:
- 靜默報告模式
- 通知報告模式
- 對話方塊報告模式
- 頁面報告模式
有 6 種處理程式型別:
- Console 處理程式
- Http 處理程式
- 檔案處理程式
- Toast 處理程式
- 自動郵件處理程式
- 手動郵件處理程式
當你建立 Catcher 例項的時候,它將會啟動你的根 Widget 並偵聽應用程式中發生的任何錯誤。在除錯模式下執行上面的程式碼,一旦有錯誤發生,將會顯示一個對話方塊,使用者可以在對話方塊中做出是否報告錯誤的決策。一旦使用者接受報告錯誤,錯誤將由 Console 處理程式處理錯誤並將錯誤資訊簡單地列印到 Console 中。
你可以在 這裡 找到基礎示例的完整程式碼。
使用對話方塊報告模式和 Console 處理程式的基礎示例,Console 中顯示了完整的報告資料
報告模式
讓我們談一談報告的模式。如你所知,報告模式是我們向用戶顯示錯誤資訊的方式。下面,讓我們更詳細的瞭解一下每種報告模式。
靜默報告模式 是一種不需要使用者做任何操作的模式。不會有任何錯誤相關的資訊顯示給使用者。使用者也不會知道任何關於錯誤的情況,除非有一些視覺化的處理程式顯示了錯誤資訊(例如,Toast 處理程式)。當你不想詢問使用者以獲取處理錯誤的許可權時,你可以使用此報告模式。
示例程式碼:
CatcherOptions(SilentReportMode(), [ConsoleHandler()]);複製程式碼
通知報告模式 顯示使用者本地通知。一旦使用者點選了它,報告將被配置的處理程式接受並處理。
示例程式碼:
CatcherOptions(NotificationReportMode(), [ConsoleHandler()]);複製程式碼
對話方塊報告模式 會向用戶顯示一個對話方塊。對話方塊中有兩個按鈕:“同意”和“取消”。點選“同意”按鈕將推送錯誤日誌到處理程式,點選“取消”將解除報告。
CatcherOptions( DialogReportMode( titleText: "Title", descriptionText: "Description", acceptText: "Accept", cancelText: "Cancel"), [ConsoleHandler()]);複製程式碼
頁面報告模式 顯示一個新的全屏頁面,其中包括錯誤描述資訊、棧跟蹤、和兩個按鈕。
CatcherOptions( PageReportMode( titleText: "Title", descriptionText: "Description", acceptText: "Accept", cancelText: "Cancel", showStackTrace: false), [ConsoleHandler()]);複製程式碼
對話方塊報告模式和頁面報告模式需要在應用中配置 navigation key 。這是非常簡單的,你只需要在你的 MaterialApp widget 中增加一行程式碼。
@overrideWidget build(BuildContext context) { return MaterialApp( //******************************************** navigatorKey: Catcher.navigatorKey, //******************************************** home: Scaffold( appBar: AppBar( title: const Text('Plugin example app'), ), body: ChildWidget()), ); }複製程式碼
報告模式有多個配置選項。你可以在 這裡 找到所有的配置項。
報告模式(從上到下依次為):通知模式,對話方塊模式,頁面模式。靜默模式沒有任何可視介面
處理程式
在報告流程中,處理程式是最後一個環節。它們消費報告並對報告做一些處理。在每一個配置組中,你可以設定多個處理程式,例如 Console 處理程式、檔案處理程式。讓我們更進一步地瞭解每一種 處理程式。
Console 處理程式 是一個基本的處理程式。它會列印格式化的報告到控制檯中。你可以配置 Console 處理程式列印或不列印報告的某些部分。
示例程式碼:
CatcherOptions(DialogReportMode(), [ ConsoleHandler( enableApplicationParameters: true, enableCustomParameters: true, enableStackTrace: true, enableDeviceParameters: true) ]);複製程式碼
控制檯處理程式
檔案處理程式 把錯誤日誌儲存到使用者的裝置中。你只需傳入儲存檔案的路徑。
示例程式碼:
Directory externalDir = await getExternalStorageDirectory(); String path = externalDir.path.toString() + "/log.txt"; CatcherOptions debugOptions = CatcherOptions(DialogReportMode(), [FileHandler(File(path))]); CatcherOptions releaseOptions = CatcherOptions(DialogReportMode(), [FileHandler(File(path))]); Catcher(MyApp(), debugConfig: debugOptions, releaseConfig: releaseOptions);複製程式碼
檔案處理程式儲存報告到檔案中
Http 處理程式 允許使用者通過 Http 請求傳送資料到伺服器。目前,只支援 Http POST 方式的請求。你可以在請求中新增自定義的 header。
示例程式碼:
CatcherOptions(DialogReportMode(), [ HttpHandler(HttpRequestType.post, Uri.parse("http://logs.server.com"), headers: {"header": "value"}, requestTimeout: 4000, printLogs: false) ]);複製程式碼
有一個用 Java 實現的簡單的 Catcher 報告服務端。你可以在 這裡 找到。
後端伺服器顯示了收集到的報告。
自動郵件處理程式 增加了發郵件功能。此處理程式自動傳送郵件到指定的郵箱。你需要設定好用於傳送郵件的使用者名稱和密碼,因此,我推薦僅在開發階段使用此處理方式。
示例程式碼:
CatcherOptions(DialogReportMode(), [EmailAutoHandler( "smtp.gmail.com", 587, "[email protected]", "Catcher", "FakePassword", ["[email protected]"]) ]);複製程式碼
從自動郵件處理程式收到的郵件。
手動郵件處理程式 與自動郵件處理程式不同。此處理程式建立郵件並開啟預設的郵件應用。使用者需要完成傳送郵件的操作。你無需指定發件人的使用者名稱和密碼,因為使用者會將使用他自己的郵箱作為發件人,所以,在釋出階段使用此方式是安全的。
示例程式碼:
CatcherOptions(DialogReportMode(), [ EmailManualHandler(["[email protected]", "[email protected]"], enableDeviceParameters: true, enableStackTrace: true, enableCustomParameters: true, enableApplicationParameters: true, sendHtml: true, emailTitle: "Sample Title", emailHeader: "Sample Header", printLogs: true) ]);複製程式碼
郵件處理程式生成的示例郵件
Toast 處理程式 是最後一種處理程式。它在使用者螢幕上顯示 toast 。當你只需要給使用者顯示簡短的資訊時,這非常有用。
示例:
CatcherOptions(DialogReportMode(), [ ToastHandler( gravity: ToastHandlerGravity.bottom, length: ToastHandlerLength.long, backgroundColor: Colors.red, textColor: Colors.white, textSize: 12.0, customMessage: "We are sorry but unexpected error occured.") ]);複製程式碼
Toast 處理程式顯示帶有錯誤資訊的 Toast
所有處理程式和它們的配置選項的介紹可以在 這裡 找到。
你甚至可以定義你自己的處理程式!只需要建立一個繼承自 ReportHandler
的類:
import 'package:catcher/catcher_plugin.dart'; class MyHandler extends ReportHandler{ @overrideFuture<bool> handle(Report error) async{ //my implementation return true; } }複製程式碼
小結
Catcher 是一個新的外掛,但是很強大。此外掛還在開發中,但你可以在你的專案中使用了。在你的專案中實現它非常的簡單直接,值得一試!
你可以在 GitHub 中自由地報告問題或提供反饋,也歡迎你向 Catcher 增加新的功能。歡迎自由地為這個專案做貢獻!
專案 GitHub 地址: github.com/jhomlala/ca…
謝謝閱讀!