簡體   English   中英

Flutter 捕獲所有未處理的異常

[英]Flutter catching all unhandled exceptions

我試圖在 Flutter 應用程序中捕獲所有未處理的異常,以便將其發送給崩潰報告者。 Flutter 文檔中關於如何執行此操作的說明 我遵循了這些,並在我的應用程序中添加了兩段代碼以捕獲異常:

通過將runApp包裝在runZoned捕獲 Dart 錯誤:

runZoned<Future<void>>(
  () async {
    runApp(MyApp());
  },
  onError: (dynamic error, StackTrace stackTrace) {
    print("=================== CAUGHT DART ERROR");
    // Send report
  },
);

通過設置FlutterError.onError捕捉顫振錯誤:

FlutterError.onError = (FlutterErrorDetails details) {
  print("=================== CAUGHT FLUTTER ERROR");
  // Send report
};

但是,當我在運行時通過從按鈕拋出異常進行測試時:

throw Exception("Just testing");

控制台中出現異常:

========被手勢捕獲的異常====================================== ========================= 處理手勢時拋出以下_異常: 異常:只是測試拋出異常時,這是堆棧:

... 等等

但是我看不到我的打印語句的跡象(CAUGHT DART ERROR 或 CAUGHT FLUTTER ERROR),並且在這些行上設置斷點似乎永遠不會命中,所以我認為我的異常處理代碼沒有捕捉到它。 我錯過了什么嗎?

這是一個最小的可重現示例(單擊按鈕,該按鈕會引發異常,但未按預期捕獲):

import 'dart:async';
import 'package:flutter/material.dart';

void main() =>
  runZoned<Future<void>>(
    () async {
      runApp(MyApp());
    },
    onError: (dynamic error, StackTrace stackTrace) {
      print("=================== CAUGHT DART ERROR");
      // Send report
      // NEVER REACHES HERE - WHY?
    },
  );

class MyApp extends StatefulWidget {
  // This widget is the root of your application.
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {

  @override
  void initState() {
    super.initState();

    // This captures errors reported by the FLUTTER framework.
    FlutterError.onError = (FlutterErrorDetails details) {
      print("=================== CAUGHT FLUTTER ERROR");
      // Send report
      // NEVER REACHES HERE - WHY?
    };
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: SafeArea(
          child: RaisedButton(
            child: Text("Throw exception"),
            onPressed: () {
              throw Exception("This is a test exception");
            },
          ),
        ),
      ),
    );
  }
}

好吧,我想通了是怎么回事。 查看了一些相關的 Flutter 問題:

flutter 工具在捕獲異常方面過於激進

使熱模式在捕捉錯誤方面不那么激進

附加調試器時中斷“未處理的”異常

看起來在調試模式下,flutter 框架捕獲了很多異常,打印到控制台(有時在 UI 本身中以紅色和黃色顯示),但不會重新拋出 - 所以它們被有效地吞下,並且有您自己的代碼無法捕獲它們。 但是,當您在發布模式下部署時,這不會發生。 因此,我的最小可重現示例在以發布模式構建時確實會捕獲異常。

注意:使用 runZonedGuarded 更新了 onError deprecated 警告的示例代碼

@james Allen我認為所有未處理的錯誤都可以全局捕獲,並且無論模式如何,它都可以在控制台中處理或打印。 在您的示例中,我認為您在設置flutterError.onError之前錯過了添加這一行WidgetsFlutterBinding.ensureInitialized()以便它可以像您一樣工作,但除外。

為了處理 flutter 中unhandled exceptions ,我們從這些安全包裝中獲得幫助以捕獲這些異常,如下所列

  • 區域(捕獲所有unhandled-asynchronous-errors
  • FlutterError.onError(捕獲所有unhandled-flutter-framework-errors

區域:

zone 不屬於 flutter 框架,它來自 dart 本身。 在 dart 文檔中,它指出..

區域保護您的應用程序不會因異步代碼引發的未捕獲異常而退出

參考鏈接https : //dart.dev/articles/archive/zones#handling-asynchronous-errors

因此,通過將我們的應用程序包裝在 zone 內到我們的 flutter 應用程序,有助於捕獲其簡單代碼下方的所有未處理的異步錯誤。

示例

void main() {
  runZonedGuarded(() async {
    runApp(MyApp()); // starting point of app
   },(error, stackTrace) {
      print("Error FROM OUT_SIDE FRAMEWORK ");
      print("--------------------------------");
      print("Error :  $error");
      print("StackTrace :  $stackTrace");
  });
 }

FlutterError.onError :

來自官方顫振文檔,它說,

Flutter 框架會捕獲在框架本身觸發的回調期間發生的錯誤,包括在構建、布局和繪制期間。

所有這些錯誤都被路由到 FlutterError.onError 處理程序。 默認情況下,這會調用 FlutterError.dumpErrorToConsole,

參考鏈接https : //flutter.dev/docs/testing/errors

所以通過使用flutterError.onError我們可以捕獲所有與 flutter 框架相關的錯誤,下面是它的簡單示例..

例子:

void main() {
    WidgetsFlutterBinding.ensureInitialized(); //imp line need to be added first
    FlutterError.onError = (FlutterErrorDetails details) {
    //this line prints the default flutter gesture caught exception in console
    //FlutterError.dumpErrorToConsole(details);
    print("Error From INSIDE FRAME_WORK");
    print("----------------------");
    print("Error :  ${details.exception}");
    print("StackTrace :  ${details.stack}");
    };
    runApp(MyApp()); // starting point of app
 }

在設置WidgetsFlutterBinding.ensureInitialized()框架的錯誤捕獲助手之前,不要忘記先添加這一行WidgetsFlutterBinding.ensureInitialized()

注意

  1. flutter 紅屏死機錯誤也會在flutterError.onError catcher下捕獲。
  2. 默認情況下,Flutter 紅屏將在開發模式下在生產環境中可見,它與 Flutter 文檔中的 BG 一樣簡單。
  3. Flutter screen to death 可以根據我們的創造力進行定制。
  4. Flutter 不會殺死應用程序,即使這些幫助程序不處理異常。
  5. 獎勵之一 - 這些也是 pub.dev 中稱為catcher的庫,您可以查看錯誤捕獲。

結合 dart 和 flutter 框架中的這兩個助手,我們可以全局捕獲所有未處理的錯誤,這些都是我在 Flutter 中被分配執行全局異常處理任務時從 Web 文檔中了解到的,如果有任何錯誤,請隨時糾正我。

所以 'runZoned' 和 'Flutter.onError' 分別用於 dart 和 flutter 框架中的 'error' 處理。 但是在您的代碼中,您正在拋出一個“異常”。 這不是由“run..”或“..onErr”處理的。 如果想在控制台看到“Just testing”,修改throw語句如下-> throw“Just testing”; 您將在控制台日志中看到它。

確保你像這樣使用WidgetsFlutterBinding.ensureInitialized()

runZonedGuarded(() {
  WidgetsFlutterBinding.ensureInitialized();
  FlutterError.onError = (FlutterErrorDetails errorDetails) {
    Utilities.log("Will log here ${errorDetails.exception.toString()}");
  };
  runApp(app);
}, (error, stackTrace) {
  Utilities.log("For other catch ${error.toString()}");
});

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM