[英]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 框架捕獲了很多異常,打印到控制台(有時在 UI 本身中以紅色和黃色顯示),但不會重新拋出 - 所以它們被有效地吞下,並且有您自己的代碼無法捕獲它們。 但是,當您在發布模式下部署時,這不會發生。 因此,我的最小可重現示例在以發布模式構建時確實會捕獲異常。
注意:使用 runZonedGuarded 更新了 onError deprecated 警告的示例代碼
嗨@james Allen我認為所有未處理的錯誤都可以全局捕獲,並且無論模式如何,它都可以在控制台中處理或打印。 在您的示例中,我認為您在設置flutterError.onError
之前錯過了添加這一行WidgetsFlutterBinding.ensureInitialized()
以便它可以像您一樣工作,但除外。
為了處理 flutter 中unhandled exceptions
,我們從這些安全包裝中獲得幫助以捕獲這些異常,如下所列
unhandled-asynchronous-errors
)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");
});
}
來自官方顫振文檔,它說,
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()
。
注意:
結合 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.