Flutter调试工具插件flutter_debug_overlay的使用
Flutter调试工具插件flutter_debug_overlay的使用
flutter_debug_overlay
是一个强大的Flutter调试工具插件,允许你在应用中实现一个覆盖层(overlay),方便在远离计算机的情况下进行调试。它提供了多种功能,如日志显示、HTTP请求检查和自定义小部件等。
特性
- 全局覆盖层:即使在应用导航之上也能使用。
- 可定制触发器:
- 移动/触摸:按住两个手指在屏幕上。
- 桌面/键盘:按下
ALT+F12
。
- 自定义小部件:支持从应用中的任何地方启用全局操作。
- 日志查看器:以整齐有序的方式显示日志。
- HTTP请求检查器:允许你检查记录的HTTP请求,包括JSON查看器。
- 提供的HTTP中间件:支持多个中间件选项来记录HTTP请求,例如
DioLogInterceptor
、HttpClientLogAdapter
和HttpLogClient
。
使用方法
简单方式
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
属性来编程控制它。
添加日志条目
- 创建一个
LogBucket
实例。 - 将实例提供给
DebugOverlay
小部件。 - 通过
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请求
- 创建一个
HttpBucket
实例。 - 将实例提供给
DebugOverlay
小部件。 - 通过以下方式将请求添加到桶中:
- 使用提供的中间件(例如
DioLogInterceptor
、HttpClientLogAdapter
和HttpLogClient
)。 - 通过
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
更多关于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});
}
注意事项
- 仅在调试模式下启用:通过将
enabled: kDebugMode
,你可以确保调试覆盖层仅在调试模式下可见,而在发布模式下不会显示。 - 自定义调试信息:你可以根据需要添加更多的调试信息到
DebugOverlayWidget
中。 - 位置调整:通过调整
Padding
和MainAxisAlignment
等参数,你可以自定义调试覆盖层的位置和样式。
这个示例展示了如何初始化和使用 flutter_debug_overlay
插件来显示 FPS 和帧时间等调试信息。你可以根据自己的需求进一步扩展和定制这个调试覆盖层。