說明:這是一篇介紹 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 configuration CatcherOptions debugOptions =
CatcherOptions(DialogReportMode(), [ConsoleHandler()]);
//release configuration
CatcherOptions releaseOptions = CatcherOptions(DialogReportMode(), [
EmailManualHandler(["recipient@email.com"]) ]);
//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 中增加一行程式碼。
@override Widget 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,
"somefakeemail@gmail.com",
"Catcher",
"FakePassword", ["myemail@gmail.com"])
]);複製程式碼
從自動郵件處理程式收到的郵件。
手動郵件處理程式與自動郵件處理程式不同。此處理程式建立郵件並開啟預設的郵件應用。使用者需要完成傳送郵件的操作。你無需指定發件人的使用者名稱和密碼,因為使用者會將使用他自己的郵箱作為發件人,所以,在釋出階段使用此方式是安全的。
示例程式碼:
CatcherOptions(DialogReportMode(), [
EmailManualHandler(["email1@email.com", "email2@email.com"],
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{
@override Future<bool> handle(Report error) async{
//my implementation
return true;
}
}複製程式碼
小結
Catcher 是一個新的外掛,但是很強大。此外掛還在開發中,但你可以在你的專案中使用了。在你的專案中實現它非常的簡單直接,值得一試!
你可以在 GitHub 中自由地報告問題或提供反饋,也歡迎你向 Catcher 增加新的功能。歡迎自由地為這個專案做貢獻!
專案 GitHub 地址:github.com/jhomlala/ca…
謝謝閱讀!