Flutter调试工具插件flutter_debug_overlay的使用

发布于 1周前 作者 bupafengyu 来自 Flutter

Flutter调试工具插件flutter_debug_overlay的使用

flutter_debug_overlay 是一个强大的Flutter调试工具插件,允许你在应用中实现一个覆盖层(overlay),方便在远离计算机的情况下进行调试。它提供了多种功能,如日志显示、HTTP请求检查和自定义小部件等。

特性

  • 全局覆盖层:即使在应用导航之上也能使用。
  • 可定制触发器
    • 移动/触摸:按住两个手指在屏幕上。
    • 桌面/键盘:按下 ALT+F12
  • 自定义小部件:支持从应用中的任何地方启用全局操作。
  • 日志查看器:以整齐有序的方式显示日志。
  • HTTP请求检查器:允许你检查记录的HTTP请求,包括JSON查看器。
  • 提供的HTTP中间件:支持多个中间件选项来记录HTTP请求,例如 DioLogInterceptorHttpClientLogAdapterHttpLogClient

使用方法

简单方式

import 'package:flutter_debug_overlay/flutter_debug_overlay.dart';

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      builder: DebugOverlay.builder(),
      home: const MyHomePage(),
    );
  }
}

高级方式

import 'package:flutter_debug_overlay/flutter_debug_overlay.dart';

class MyApp extends StatelessWidget {
  static final LogBucket logBucket = LogBucket();
  static final HttpBucket httpBucket = HttpBucket();

  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      builder: (context, child) {
        return DebugOverlay(
          hiddenFields: const [HttpHeaders.authorizationHeader, "Token"],
          logBucket: logBucket,
          httpBucket: httpBucket,
          debugEntries: [ExampleDebug()],
          child: child ?? const SizedBox.shrink(),
        );
      },
      home: const MyHomePage(),
    );
  }
}

打开覆盖层

默认情况下,可以通过以下方式打开覆盖层:

  • 在移动设备上,按住两个手指。
  • 在桌面设备上,按下 ALT+F12

你也可以通过 DebugOverlay 小部件的 visible 属性来编程控制它。

添加日志条目

  1. 创建一个 LogBucket 实例。
  2. 将实例提供给 DebugOverlay 小部件。
  3. 通过 add 方法将日志添加到桶中。

示例日志源

  • 使用 logger 包连接到覆盖层:
import 'package:logger/logger.dart' hide LogEvent;

Logger.addOutputListener((event) {
  LogLevel? level = LogLevel.values.firstWhereOrNull((element) => element.name == event.origin.level.name);
  if (level == null) return;
  MyApp.logBucket.add(LogEvent(
    level: level,
    message: event.origin.message,
    error: event.origin.error,
    stackTrace: event.origin.stackTrace,
    time: event.origin.time,
  ));
});
  • 处理Flutter错误(例如渲染异常):
FlutterError.onError = (details) {
  FlutterError.presentError(details);
  MyApp.logBucket.add(LogEvent(
    level: LogLevel.fatal,
    message: details.exceptionAsString(),
    error: (kDebugMode ? details.toDiagnosticsNode().toStringDeep() : details.exception.toString()),
    stackTrace: details.stack,
  ));
};
  • 处理未捕获的异常:
PlatformDispatcher.instance.onError = (exception, stackTrace) {
  MyApp.logBucket.add(LogEvent(
    level: LogLevel.fatal,
    message: "Unhandled Exception",
    error: exception,
    stackTrace: stackTrace,
  ));
  return false; // "false" still dumps it to the console.
};

添加HTTP请求

  1. 创建一个 HttpBucket 实例。
  2. 将实例提供给 DebugOverlay 小部件。
  3. 通过以下方式将请求添加到桶中:
    • 使用提供的中间件(例如 DioLogInterceptorHttpClientLogAdapterHttpLogClient)。
    • 通过 add 方法手动添加。

示例HTTP客户端集成

  • 使用 Dio
dio = Dio()..interceptors.add(DioLogInterceptor(MyApp.httpBucket));
  • 使用 HttpClient (dart:io):
httpClient = HttpClient();
httpClientAdapter = HttpClientLogAdapter(MyApp.httpBucket);

// Log request
httpClientAdapter.onRequest(request);

// Log response
httpClientAdapter.onResponse(request, response, responseBody);

// Log error
httpClientAdapter.onError(request, error, stackTrace);
  • 使用 "http" 包:
client = HttpLogClient(MyApp.httpBucket, http.Client());

完整示例Demo

import 'dart:async';
import 'dart:convert';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter_debug_overlay/flutter_debug_overlay.dart';
import 'package:http/http.dart' as http;
import 'package:logger/logger.dart' hide LogEvent;

void main() {
  DebugOverlay.enabled = true;

  PlatformDispatcher.instance.onError = (exception, stackTrace) {
    MyApp.logBucket.add(LogEvent(
      level: LogLevel.fatal,
      message: "Unhandled Exception",
      error: exception,
      stackTrace: stackTrace,
    ));
    return false;
  };

  FlutterError.onError = (details) {
    FlutterError.presentError(details);
    MyApp.logBucket.add(LogEvent(
      level: LogLevel.fatal,
      message: details.exceptionAsString(),
      error: (kDebugMode
          ? details.toDiagnosticsNode().toStringDeep()
          : details.exception.toString()),
      stackTrace: details.stack,
    ));
  };

  Logger.addOutputListener((event) {
    LogLevel? level = LogLevel.values.firstWhereOrNull((element) => element.name == event.origin.level.name);
    if (level == null) return;
    MyApp.logBucket.add(LogEvent(
      level: level,
      message: event.origin.message,
      error: event.origin.error,
      stackTrace: event.origin.stackTrace,
      time: event.origin.time,
    ));
  });

  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  static final Logger logger = Logger();
  static final LogBucket logBucket = LogBucket();
  static final HttpBucket httpBucket = HttpBucket();

  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  ThemeMode? _forcedTheme;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: "Flutter Debug Demo",
      themeMode: _forcedTheme ?? ThemeMode.system,
      theme: ThemeData(),
      darkTheme: ThemeData.dark(),
      builder: DebugOverlay.builder(
        logBucket: MyApp.logBucket,
        httpBucket: MyApp.httpBucket,
        debugEntries: [
          ExampleDebug(
            onThemeChange: ([ThemeMode? themeMode]) => setState(() {
              _forcedTheme = themeMode;
            }),
          ),
        ],
      ),
      home: const MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  static Uri baseUrl = Uri.parse("https://httpstat.us/");

  late final Dio dio;

  @override
  void initState() {
    super.initState();
    dio = Dio()..interceptors.add(DioLogInterceptor(MyApp.httpBucket));
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("Flutter Debug Demo")),
      body: Center(
        child: Column(
          children: [
            ElevatedButton(
              onPressed: () {
                MyApp.logger.i("User requested update");
              },
              child: const Text("Info Log"),
            ),
            ElevatedButton(
              onPressed: () {
                _sendDioRequest();
              },
              child: const Text("Dio HTTP Request"),
            ),
          ],
        ),
      ),
    );
  }

  Future<void> _sendDioRequest() {
    return dio.putUri(
      baseUrl.replace(path: "201"),
      data: json.decode("""
{
  "id": 1,
  "first_name": "Garvy",
  "last_name": "Fencott",
  "gender": "Male",
  "ip_address": "214.62.102.43"
}"""),
      options: Options(
        contentType: "application/octet-stream",
        validateStatus: (status) => true,
      ),
    ).then((value) => print("Received Dio response: $value"))
     .catchError((e, stack) => print("Dio request failed", error: e, stackTrace: stack));
  }
}

这个完整的示例展示了如何在你的Flutter应用中集成 flutter_debug_overlay 插件,并利用其丰富的功能来进行调试。希望这些信息对你有所帮助!


更多关于Flutter调试工具插件flutter_debug_overlay的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter调试工具插件flutter_debug_overlay的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,flutter_debug_overlay 是一个在 Flutter 开发中非常有用的插件,它提供了一个可定制的调试覆盖层,用于在应用程序中显示有用的调试信息。以下是如何在 Flutter 项目中使用 flutter_debug_overlay 的详细步骤和代码示例。

步骤 1:添加依赖

首先,你需要在 pubspec.yaml 文件中添加 flutter_debug_overlay 依赖。

dependencies:
  flutter:
    sdk: flutter
  flutter_debug_overlay: ^x.y.z  # 替换为最新版本号

然后运行 flutter pub get 来获取依赖。

步骤 2:导入包

在你的 Flutter 项目的 Dart 文件中导入 flutter_debug_overlay 包。

import 'package:flutter_debug_overlay/flutter_debug_overlay.dart';

步骤 3:初始化和使用

你可以在你的应用程序的入口点(通常是 main.dart 文件)中初始化 flutter_debug_overlay。以下是一个完整的示例,展示了如何初始化并使用该插件。

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

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // 初始化 FlutterDebugOverlay
    FlutterDebugOverlay.init(
      enabled: kDebugMode,  // 仅在调试模式下启用
      builder: (context) => DebugOverlayWidget(
        // 配置你想要显示的调试信息
        children: [
          DebugOverlayInfo(
            title: 'FPS',
            value: FlutterDebugOverlayData.of(context)?.fps?.toString() ?? 'N/A',
          ),
          DebugOverlayInfo(
            title: 'Frame Time',
            value: FlutterDebugOverlayData.of(context)?.frameTime?.toString() ?? 'N/A',
          ),
          // 你可以添加更多的调试信息
        ],
      ),
    );

    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Flutter Debug Overlay Example'),
        ),
        body: Center(
          child: Text('Check the top right corner for debug overlay!'),
        ),
      ),
    );
  }
}

// 自定义的 DebugOverlayWidget(可选)
class DebugOverlayWidget extends StatelessWidget {
  final List<DebugOverlayInfo> children;

  const DebugOverlayWidget({Key? key, required this.children}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.end,
      crossAxisAlignment: CrossAxisAlignment.end,
      children: [
        for (final info in children)
          Padding(
            padding: EdgeInsets.only(right: 8.0, bottom: 4.0),
            child: Row(
              children: [
                Text(info.title),
                SizedBox(width: 8.0),
                Text(info.value),
              ],
            ),
          ),
      ],
    );
  }
}

class DebugOverlayInfo {
  final String title;
  final String value;

  const DebugOverlayInfo({required this.title, required this.value});
}

注意事项

  1. 仅在调试模式下启用:通过将 enabled: kDebugMode,你可以确保调试覆盖层仅在调试模式下可见,而在发布模式下不会显示。
  2. 自定义调试信息:你可以根据需要添加更多的调试信息到 DebugOverlayWidget 中。
  3. 位置调整:通过调整 PaddingMainAxisAlignment 等参数,你可以自定义调试覆盖层的位置和样式。

这个示例展示了如何初始化和使用 flutter_debug_overlay 插件来显示 FPS 和帧时间等调试信息。你可以根据自己的需求进一步扩展和定制这个调试覆盖层。

回到顶部