[譯] 使用 Catcher 處理 Flutter 錯誤

芙蓉秋江發表於2019-02-14
說明:這是一篇介紹 Flutter 錯誤處理的文章,翻譯自國外的一篇部落格,若有翻譯不準確或文字表達上的不足之處,歡迎指正。原文連結:https://medium.com/flutter-community/handling-flutter-errors-with-catcher-efce74397862
作者:
Jakub Homlala

[譯] 使用 Catcher 處理 Flutter 錯誤

本圖片源自UnsplashChor Hung Tsang

錯誤處理是程式設計師每天的工作,這事兒在日常工作中是沒完沒了的。在 Dart 語言中,我們可以用 try-catch 語言結構輕鬆地處理錯誤。但是,如果我們忘了寫 try-catch 程式碼會怎樣?我們會得到一個像下面這樣的“紅屏錯誤頁面”。

[譯] 使用 Catcher 處理 Flutter 錯誤

是的,我們的程式碼不都總是執行良好。每一個開發者都會有疏忽。但好的開發者會解決他所犯的失誤。

對使用者來說,一個重要的事情是,當我們是一個 APP 的使用者的時候,我們需要知道一些超出預期的事發生了,並且我們可以決定是否傳送錯誤日誌給開發者。錯誤日誌會幫助開發者修復錯誤。

開發者能修復錯誤,但他們需要知道發生了什麼錯誤和在哪兒發生的錯誤。在移動應用開發中,我們需要一個可以報告程式異常行為給開發者的工具。目前,在 Flutter 中我們已經支援了 Sentry 錯誤追蹤功能,很快也會支援 Firebase 的 Crashlytics。但是,如果我們不想使用 Sentry 或 Crashlytics 怎麼辦呢?如果我們使用一些配置簡單,還可以在開發階段甚至在已釋出後捕獲錯誤的通用的工具,那該怎麼實現呢?這個工具包含傳送郵件的功能,使用者只需點選“傳送” 就可以把錯誤反饋給開發者,或者把崩潰日誌儲存到裝置的儲存器中。這就是接下來將要介紹的 Catcher 了。

Catcher 簡介

[譯] 使用 Catcher 處理 Flutter 錯誤

Catcher 的 logo

Catcher 是一個新的捕獲和處理錯誤資訊的 Flutter 外掛。Catcher 提供多種錯誤報告模型和處理程式,以配合 Flutter 應用程式。Catcher 深受 ACRA 的啟發。

Catcher 報告流程是很容易理解的(參看下圖)。Catcher 將錯誤處理程式注入到你的應用程式中,從而可以捕獲所有未經檢測的錯誤。一旦它捕獲到錯誤,他就建立報告並將其傳送到reporter 中。reporter 顯示錯誤的相關資訊並等待使用者決策。如果使用者接受報告錯誤,則處理程式(handlers)將處理該報告。

你也可以報告你在 try catch 中檢查到的錯誤。

Catcher 也會收集使用者裝置硬體和作業系統的資訊。這些資料的獲取是可以不經使用者任何形式的授權,因為它不含有使用者的個人資訊。這些資料是很有幫助的,因為有些時候產生錯誤是因為裝置的問題而不是開發者的問題。

[譯] 使用 Catcher 處理 Flutter 錯誤

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 , releaseprofile 。在上面的程式碼中,我們建立了 3 個 CatcherOptions 例項,分別描述 Catcher 在不同模式下的行為方式。當應用執行在 debug 環境時,Catcher 會使用 debugConfig ,當應用執行在釋出環境時會使用 releaseConfig 當執行在 “profile” 模式時,會使用 profileConfig

在每一個 CatcherOptions 例項中,你可以配置不同的 報告模型和處理程式列表。點選這裡可以檢視 CatcherOptions 的所有的配置引數。

有 4 種報告模式:

  • 靜默報告模式
  • 通知報告模式
  • 對話方塊報告模式
  • 頁面報告模式

有 6 種處理程式型別:

  • Console 處理程式
  • Http 處理程式
  • 檔案處理程式
  • Toast 處理程式
  • 自動郵件處理程式
  • 手動郵件處理程式


當你建立 Catcher 例項的時候,它將會啟動你的根 Widget 並偵聽應用程式中發生的任何錯誤。在除錯模式下執行上面的程式碼,一旦有錯誤發生,將會顯示一個對話方塊,使用者可以在對話方塊中做出是否報告錯誤的決策。一旦使用者接受報告錯誤,錯誤將由 Console 處理程式處理錯誤並將錯誤資訊簡單地列印到 Console 中。

你可以在這裡找到基礎示例的完整程式碼。

[譯] 使用 Catcher 處理 Flutter 錯誤

[譯] 使用 Catcher 處理 Flutter 錯誤

使用對話方塊報告模式和 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()),
    );
  }複製程式碼

報告模式有多個配置選項。你可以在這裡找到所有的配置項。

[譯] 使用 Catcher 處理 Flutter 錯誤[譯] 使用 Catcher 處理 Flutter 錯誤

[譯] 使用 Catcher 處理 Flutter 錯誤

報告模式(從上到下依次為):通知模式,對話方塊模式,頁面模式。靜默模式沒有任何可視介面

處理程式

在報告流程中,處理程式是最後一個環節。它們消費報告並對報告做一些處理。在每一個配置組中,你可以設定多個處理程式,例如 Console 處理程式、檔案處理程式。讓我們更進一步地瞭解每一種 處理程式。

Console 處理程式 是一個基本的處理程式。它會列印格式化的報告到控制檯中。你可以配置 Console 處理程式列印或不列印報告的某些部分。

示例程式碼:

CatcherOptions(DialogReportMode(), [
  ConsoleHandler(
      enableApplicationParameters: true,
      enableCustomParameters: true,
      enableStackTrace: true,
      enableDeviceParameters: true)
]);複製程式碼

[譯] 使用 Catcher 處理 Flutter 錯誤

控制檯處理程式


檔案處理程式把錯誤日誌儲存到使用者的裝置中。你只需傳入儲存檔案的路徑。

示例程式碼:

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);複製程式碼

[譯] 使用 Catcher 處理 Flutter 錯誤

檔案處理程式儲存報告到檔案中

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 報告服務端。你可以在這裡找到。

[譯] 使用 Catcher 處理 Flutter 錯誤

後端伺服器顯示了收集到的報告。

自動郵件處理程式增加了發郵件功能。此處理程式自動傳送郵件到指定的郵箱。你需要設定好用於傳送郵件的使用者名稱和密碼,因此,我推薦僅在開發階段使用此處理方式。

示例程式碼:

CatcherOptions(DialogReportMode(),
    [EmailAutoHandler(
        "smtp.gmail.com", 587,
        "somefakeemail@gmail.com",
        "Catcher", 
       "FakePassword", ["myemail@gmail.com"])
    ]);複製程式碼

[譯] 使用 Catcher 處理 Flutter 錯誤

從自動郵件處理程式收到的郵件。

手動郵件處理程式與自動郵件處理程式不同。此處理程式建立郵件並開啟預設的郵件應用。使用者需要完成傳送郵件的操作。你無需指定發件人的使用者名稱和密碼,因為使用者會將使用他自己的郵箱作為發件人,所以,在釋出階段使用此方式是安全的。

示例程式碼:

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)
]);複製程式碼

[譯] 使用 Catcher 處理 Flutter 錯誤

郵件處理程式生成的示例郵件

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.")
]);複製程式碼

[譯] 使用 Catcher 處理 Flutter 錯誤

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…

謝謝閱讀!



相關文章