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),
          ],
        ),
      ),
    );
  }

}

二,测试效果:

image

点击后:

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
====================================================================================================

 

posted @ 2026-03-07 21:13  刘宏缔的架构森林  阅读(0)  评论(0)    收藏  举报