flutter:捕捉异常:
一,代码:
1,main
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import 'services/AuthService.dart';
import 'routes/routes.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
void main() {
runZonedGuarded(() {
// 第二层:Flutter框架自身的错误回调
FlutterError.onError = (FlutterErrorDetails details) {
print("捕捉到了异常");
FlutterError.presentError(details); // 开发时显示红屏
print('详情打印开始:');
String detail = details.toString();
print(detail);
print('详情打印结束:');
};
// 第三层:Widget构建时的错误边界
ErrorWidget.builder = (FlutterErrorDetails details) {
// 当Widget构建失败时,展示我们自定义的错误界面,而不是崩溃
print('Widget错误时详情打印开始:');
String detail = details.toString();
print(detail);
print('Widget错误时详情打印结束:');
return ErrorRecoveryWidget(details);
};
runApp(MyApp());
}, (error, stackTrace) {
// 处理所有未被前面捕获的异常
//_handleZoneError(error, stackTrace);
//print("处理所有未被前面捕获的异常");
//print(error);
print('未被前面捕获的异常: $error');
print('未被前面捕获的异常的堆栈: $stackTrace');
});
}
class ErrorRecoveryWidget extends StatelessWidget {
final FlutterErrorDetails errorDetails;
final VoidCallback? onRetry;
const ErrorRecoveryWidget(
this.errorDetails, {
this.onRetry,
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Material(
child: Container(
color: Colors.grey[100],
padding: const EdgeInsets.all(20),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.error_outline,
size: 64,
color: Colors.red[400],
),
const SizedBox(height: 20),
Text(
'页面加载失败',
style: Theme.of(context).textTheme.headlineMedium?.copyWith(
color: Colors.red[700],
),
),
const SizedBox(height: 12),
Text(
errorDetails.exceptionAsString(),
textAlign: TextAlign.center,
style: const TextStyle(color: Colors.grey),
maxLines: 3,
overflow: TextOverflow.ellipsis,
),
const SizedBox(height: 24),
if (onRetry != null)
ElevatedButton.icon(
onPressed: onRetry,
icon: const Icon(Icons.refresh),
label: const Text('重试'),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.blue,
foregroundColor: Colors.white,
),
),
const SizedBox(height: 16),
TextButton(
onPressed: () {
showErrorDetailsDialog(context, errorDetails);
},
child: const Text('查看错误详情'),
),
],
),
),
);
}
// 提供一个对话框展示详细的错误信息,方便调试
void showErrorDetailsDialog(BuildContext context, FlutterErrorDetails details) {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Text('错误详情'),
content: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text('异常类型:', style: TextStyle(fontWeight: FontWeight.bold)),
SelectableText(details.exception.runtimeType.toString()),
const SizedBox(height: 12),
const Text('异常信息:', style: TextStyle(fontWeight: FontWeight.bold)),
SelectableText(details.exception.toString()),
const SizedBox(height: 12),
const Text('堆栈跟踪:', style: TextStyle(fontWeight: FontWeight.bold)),
SizedBox(
height: 200,
child: SingleChildScrollView(
child: SelectableText(details.stack.toString()),
),
),
],
),
),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: const Text('关闭'),
),
TextButton(
onPressed: () {
Clipboard.setData(ClipboardData(
text: '${details.exception}\n\n${details.stack}'
));
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('已复制到剪贴板')),
);
},
child: const Text('复制'),
),
],
),
);
}
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return ScreenUtilInit(
designSize: const Size(750, 1334),
minTextAdapt: true,
splitScreenMode: true,
// Use builder only if you need to use library outside ScreenUtilInit context
builder: (_ , child) {
return GetMaterialApp(
debugShowCheckedModeBanner: false, //去除debug图标
defaultTransition: Transition.rightToLeft, //指定动画
theme: ThemeData(primarySwatch: Colors.red),
initialRoute: "/", //初始化页面
getPages: APPage.routes, //路由
);
},
);
}
}
homepage.dart
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:mylist2/utils/functions.dart';
import 'package:mylist2/views/MyButton.dart';
import '../services/AuthService.dart';
class HomePage extends StatefulWidget {
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
//按钮被点击后抛出异常
void myclick() {
print('按钮被点击过了');
throw new Exception("自定义异常aaa");
}
@override
Widget build(BuildContext context) {
const widget = null;
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: const Text("home页面"),
),
body: Center(
child:Column(
children:[
MyButton(onPressed: myclick),
],
),
),
);
}
}
二,测试效果:

点击后:
I/flutter (10164): 按钮被点击过了
I/flutter (10164): 捕捉到了异常
I/flutter (10164): 详情打印开始:
I/flutter (10164): ══╡ EXCEPTION CAUGHT BY GESTURE ╞════════════════════════════════
I/flutter (10164): The following _Exception was thrown while handling a gesture:
I/flutter (10164): Exception: 自定义异常aaa
I/flutter (10164):
I/flutter (10164): When the exception was thrown, this was the stack:
I/flutter (10164): #0 _HomePageState.myclick (package:mylist2/pages/HomePage.dart:18:5)
I/flutter (10164): #1 _InkResponseState.handleTap (package:flutter/src/material/ink_well.dart:1224:21)
I/flutter (10164): #2 GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:345:24)
I/flutter (10164): #3 TapGestureRecognizer.handleTapUp (package:flutter/src/gestures/tap.dart:758:11)
I/flutter (10164): #4 BaseTapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:383:5)
I/flutter (10164): #5 BaseTapGestureRecognizer.handlePrimaryPointer (package:flutter/src/gestures/tap.dart:314:7)
I/flutter (10164): #6 PrimaryPointerGestureRecognizer.handleEvent (package:flutter/src/gestures/recognizer.dart:721:9)
I/flutter (10164): #7 PointerRouter._dispatch (package:flutter/src/gestures/pointer_router.dart:97:12)
I/flutter (10164): #8 Point
I/flutter (10164): 详情打印结束:
======== Exception caught by gesture ===============================================================
The following _Exception was thrown while handling a gesture:
Exception: 自定义异常aaa
When the exception was thrown, this was the stack:
#0 _HomePageState.myclick (package:mylist2/pages/HomePage.dart:18:5)
#1 _InkResponseState.handleTap (package:flutter/src/material/ink_well.dart:1224:21)
#2 GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:345:24)
#3 TapGestureRecognizer.handleTapUp (package:flutter/src/gestures/tap.dart:758:11)
#4 BaseTapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:383:5)
#5 BaseTapGestureRecognizer.handlePrimaryPointer (package:flutter/src/gestures/tap.dart:314:7)
#6 PrimaryPointerGestureRecognizer.handleEvent (package:flutter/src/gestures/recognizer.dart:721:9)
#7 PointerRouter._dispatch (package:flutter/src/gestures/pointer_router.dart:97:12)
#8 PointerRouter._dispatchEventToRoutes.<anonymous closure> (package:flutter/src/gestures/pointer_router.dart:140:9)
#9 _LinkedHashMapMixin.forEach (dart:_compact_hash:765:13)
#10 PointerRouter._dispatchEventToRoutes (package:flutter/src/gestures/pointer_router.dart:138:18)
#11 PointerRouter.route (package:flutter/src/gestures/pointer_router.dart:128:7)
#12 GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:528:19)
#13 GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:498:22)
#14 RendererBinding.dispatchEvent (package:flutter/src/rendering/binding.dart:473:11)
#15 GestureBinding._handlePointerEventImmediately (package:flutter/src/gestures/binding.dart:437:7)
#16 GestureBinding.handlePointerEvent (package:flutter/src/gestures/binding.dart:394:5)
#17 GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:341:7)
#18 GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:308:9)
#22 _invoke1 (dart:ui/hooks.dart:374:10)
#23 PlatformDispatcher._dispatchPointerDataPacket (dart:ui/platform_dispatcher.dart:467:7)
#24 _dispatchPointerDataPacket (dart:ui/hooks.dart:307:31)
(elided 3 frames from dart:async)
Handler: "onTap"
Recognizer: TapGestureRecognizer#609c1
debugOwner: GestureDetector
state: possible
won arena
finalPosition: Offset(200.0, 105.1)
finalLocalPosition: Offset(59.8, 19.1)
button: 1
sent tap down
====================================================================================================
浙公网安备 33010602011771号