调试网络请求,是移动端开发里最绕不开的日常操作之一。做 Flutter 开发时,Dio 基本是事实标准的 HTTP 客户端,而 Pretty Dio Logger 则是搭配它最顺手的一款请求日志插件。最近我把一部分 Flutter 业务迁移到 OpenHarmony 设备上跑,原以为日志工具链会有不少适配工作量,结果发现 Pretty Dio Logger 这种纯 Dart 实现的插件,在 OpenHarmony 的 Flutter 环境里几乎零成本就能用起来,体验和 Android/iOS 上完全一致。这篇文章就围绕“Flutter for OpenHarmony + Pretty Dio Logger”这套组合,写写我在实际项目里怎么配置、怎么调参、怎么拿它快速定位问题,以及那些文档里不会写清楚的坑。
不管你是刚开始接触 OpenHarmony 上的 Flutter,还是已经在做鸿蒙设备端的应用调试,这篇内容都能帮你少走点弯路。我会从选型思路讲到完整接入步骤,再给出一套可复用的封装模板,最后把几个高频问题逐个拆开讲透。
1. 项目背景与整体设计思路
1.1 为什么 Flutter 应用需要网络请求监控
很多刚入门的同学觉得,调试网络请求不就是打开 DevTools 或者抓包工具看一眼吗?但实际上,移动端网络问题是一个特别磨人的环节。你辛辛苦苦写完一个接口调用,真机上跑起来,发现页面数据没出来——这时候你根本不知道是请求根本没发出去,还是服务端返回了 500,还是 JSON 解析炸了。如果没有一个直观的请求日志输出,你只能靠猜,或者去抓包工具里翻半天。
抓包工具(比如 Charles、Fiddler)虽然功能强大,但在真机上配置代理、装证书,本身就有一堆成本。尤其是 OpenHarmony 这类新平台,抓包工具的兼容性还不一定跟得上。而 Pretty Dio Logger 这种日志插件的好处是:它不依赖任何外部代理,直接在应用进程里拦截 Dio 的请求和响应,把关键信息打印到控制台,一键开关,随开随用。这对于日常开发调试来说,效率要高得多。
1.2 Pretty Dio Logger 能解决什么问题
简单说,Pretty Dio Logger 是一个 Dart 包,以 Dio 拦截器(Interceptor)的形式工作。你只需要在创建 Dio 实例时把它加进 interceptors 列表,之后所有的 HTTP 请求、响应、错误,都会以格式化后的可读文本输出到日志里。
它能输出的内容包括:
- 请求方法、URL、请求头、请求体
- 响应状态码、响应头、响应体
- 请求耗时(从发出到收到响应的总时间)
- 错误信息与异常堆栈
- 自定义过滤规则,比如只打印某个域名的请求,或者忽略某些敏感接口
在实际开发里,这套能力基本覆盖了日常接口调试 90% 以上的场景。而且它对已有的业务代码侵入性极低——不需要改任何接口调用逻辑,只需要在初始化 Dio 的地方加几行配置。
1.3 为什么选 Pretty Dio Logger 而不是其他方案
在 Flutter 生态里,类似的网络日志插件还有 dio_log、logger + dio_interceptor 这类组合,但 Pretty Dio Logger 有几个很实在的优势:
- 纯粹用 Dart 实现:这是它能在 OpenHarmony 上无缝运行的关键。它不依赖任何原生平台通道(PlatformChannel),也不涉及 Android/iOS 的 Native 代码,所以不需要为 OpenHarmony 做任何额外适配。相比之下,一些用原生 View 实现悬浮窗日志的插件,在 OpenHarmony 上就需要重新适配,工作量完全不是一个量级。
- 配置灵活,开箱即用:插件的默认配置已经足够漂亮,但我们也能够按需关闭请求头、压缩响应体、限制最大行数等。
- 与 Debug 模式配合默契:日志输出走的是
print/debugPrint,在 Flutter 的 Debug 控制台里看效果非常直观,也能配合kDebugMode做到生产环境自动关闭。
我当时在 OpenHarmony 真机上跑通第一版时,看到控制台里打印出格式化的请求日志,第一反应是:真的就这么简单?因为完全没动任何平台相关的代码。对于一个新兴平台来说,这种零适配体验本身就说明了 Flutter 跨端能力的价值。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 环境准备与依赖集成
2.1 OpenHarmony Flutter 开发环境的基本要求
在开始接入 Pretty Dio Logger 之前,先确保你的 OpenHarmony Flutter 开发环境是能正常跑的。这里默认你已经完成了以下基础工作:
- 安装了支持 OpenHarmony 的 Flutter SDK(通常是 OpenHarmony 官方维护的分支版本,例如
flutter_flutter仓库的harmony相关分支) - 配置好了 OpenHarmony SDK 和 IDE 环境(DevEco Studio)
- 有一台 OpenHarmony 真机或者模拟器,并且能够用
hdc命令连接上设备
连接设备后,可以用下面这个命令快速确认系统版本,顺便验证 hdc 通路是否正常:
bash复制hdc shell param get const.product.name
如果输出类似 RK3568 或 RK3588 之类的设备名称,说明连接正常。这也算是我平时判断“设备在不在线”的第一板斧。
2.2 在 pubspec.yaml 中添加依赖
在项目根目录的 pubspec.yaml 中,添加 pretty_dio_logger 依赖:
yaml复制dependencies:
flutter:
sdk: flutter
dio: ^5.4.0
pretty_dio_logger: ^2.0.0
然后执行:
bash复制flutter pub get
这里有个小提醒:pretty_dio_logger 2.x 版本要求的 Dart SDK 版本比较高,如果你的 Flutter 版本比较老,可能需要用 1.x 版本。不过 OpenHarmony 分支的 Flutter SDK 一般都会跟进较新的 Dart 版本,所以直接上 2.x 基本没问题。
2.3 初始化 Dio 并挂载 Pretty Dio Logger
引入依赖之后,创建一个 Dio 实例并添加拦截器:
dart复制import 'package:dio/dio.dart';
import 'package:pretty_dio_logger/pretty_dio_logger.dart';
Dio createDio() {
final dio = Dio(
BaseOptions(
baseUrl: 'https://api.example.com',
connectTimeout: Duration(seconds: 15),
receiveTimeout: Duration(seconds: 15),
),
);
dio.interceptors.add(
PrettyDioLogger(
requestHeader: true,
requestBody: true,
responseHeader: false,
responseBody: true,
error: true,
compact: false,
maxWidth: 90,
maxLine: 3,
),
);
return dio;
}
到这里,最基本的接入就完成了。你每发起一个请求,控制台里都会输出一张格式化好的“请求卡片”,包含 Method、URL、Headers、Body、耗时、状态码、响应体等关键信息。看着就比裸 print 舒服得多。
注意:在生产环境里不要直接这样挂载。你需要用
kDebugMode或者bool.fromEnvironment('dart.vm.product')去判断,只在 Debug 构建下启用日志拦截器,避免把敏感请求信息打到线上日志里。
3. 核心功能拆解与配置参数解析
3.1 请求头、请求体、响应体的打印策略
Pretty Dio Logger 最核心的开关就是几个 Boolean 参数:
| 参数 | 作用 | 建议值 |
|---|---|---|
requestHeader |
打印请求头 | Debug 下建议 true |
requestBody |
打印请求体 | Debug 下建议 true |
responseHeader |
打印响应头 | 一般 false,减少噪音 |
responseBody |
打印响应体 | Debug 下建议 true |
error |
打印错误与异常堆栈 | 建议 true |
compact |
是否压缩为单行输出 | 建议 false,false 时更易读 |
maxWidth |
每行最大宽度,超过则换行 | 80~120 之间比较合适 |
maxLine |
每个字段最多打印的行数 | 3 左右,防止超长 JSON 刷屏 |
我自己的习惯是,responseHeader 一般不开。因为响应头里真正有用的信息不多,还容易把控制台刷得乱七八糟。但如果你在排查缓存、跨域、重定向这类问题,那就必须把 responseHeader 打开,这时候再临时调配置就行。
3.2 compact 与 maxWidth、maxLine 的配合逻辑
compact: false 时,日志会以“展开式”输出,每个字段独占几行,适合快速浏览。而 compact: true 时,请求日志会被压缩成一行,适合在日志系统里按行检索,或者当你只需要快速确认“这个请求有没有发出”的时候用。
maxWidth 控制的是每行最大字符宽度。默认值我记得是 90,但对于一些包含长 URL 或长 token 的请求头来说,90 可能不够,会把参数换行,看起来反而更乱。我习惯把它调到 120。maxLine 的意思是,针对请求体或响应体这类大文本,最多打印的行数。比如响应体是一个超大的 JSON 数组,不加限制的话整个控制台都会刷爆,设置了 maxLine: 3 之后,第 4 行开始就会以省略号截断。
这两个参数配合起来,就是一套“既能看到全貌,又不会被刷屏”的平衡策略。
3.3 logPrint:把日志接入你自己的日志体系
有时候你的项目里已经有一套统一的日志系统(比如 logger 包,或者自研的文件日志),这时候不需要 Pretty Dio Logger 默认走 print 输出,可以用 logPrint 参数做转发:
dart复制PrettyDioLogger(
// ...其他参数
logPrint: (log) {
// 接入统一日志系统,例如:
// logger.d(log);
debugPrint(log);
},
)
这一点在 OpenHarmony 上尤其有用。因为 print 打印的日志在部分版本的 hilog 里可能不完整,你可以在 logPrint 里加一个统一前缀,然后用 hdc shell hilog | grep 去过滤,定位问题会方便很多。这部分我在第 5 节里会展开讲。
3.4 过滤不想打印的请求
默认情况下,Pretty Dio Logger 会打印所有通过该 Dio 实例发出的请求。但有些接口可能涉及敏感信息,比如登录接口的密码、支付接口的 Token,你不想它们出现在日志里。这时候可以根据请求信息做逻辑判断:如果某个请求的 URL 或 header 命中敏感规则,就不打印。
比如这样:
dart复制PrettyDioLogger(
filter: (options) {
final path = options.uri.path;
if (path.contains('/login') || path.contains('/token')) {
return false; // 不打印
}
return true;
},
)
不过说实话,filter 参数是 PrettyDioLogger 2.x 版本之后才提供的,1.x 版本没有。如果你的项目在 OpenHarmony 上用的是较老的 1.x 版本,也可以在外层包一个拦截器,通过判断来动态决定是否跳过日志打印。更简单的做法是:直接在业务侧把日志等级关掉,或者用 kDebugMode 在 Release 下不挂载这个拦截器,效果也差不多。
4. 实战:封装一个可复用的网络监控模块
4.1 定义一个支持 Debug 开关的 Dio 单例
在实际项目里,我不会在每个页面单独创建 Dio,而是封装一个全局的网络模块。这样可以统一管理拦截器、超时时间、Token 注入等逻辑。下面是我在 OpenHarmony Flutter 项目里用的一个简化版封装:
dart复制import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import 'package:pretty_dio_logger/pretty_dio_logger.dart';
class ApiClient {
ApiClient._internal();
static final ApiClient instance = ApiClient._internal();
late final Dio dio;
void init() {
dio = Dio(
BaseOptions(
baseUrl: 'https://api.example.com',
connectTimeout: const Duration(seconds: 15),
receiveTimeout: const Duration(seconds: 15),
),
);
if (kDebugMode) {
dio.interceptors.add(
PrettyDioLogger(
requestHeader: true,
requestBody: true,
responseBody: true,
error: true,
compact: false,
maxWidth: 120,
logPrint: (log) {
debugPrint('[API] $log');
},
),
);
}
// 业务拦截器:统一注入 Token、处理错误码等
dio.interceptors.add(
InterceptorsWrapper(
onRequest: (options, handler) {
// 注入 token...
handler.next(options);
},
onError: (DioException e, handler) {
// 统一错误处理...
handler.next(e);
},
),
);
}
}
注意我把 PrettyDioLogger 放在 kDebugMode 分支里。这样 Release 包天然不带网络日志,不用手动删代码。
4.2 用 GetIt 或 Provider 管理网络模块
如果项目里用了状态管理框架,比如 GetIt、Provider、Riverpod,可以直接把 Dio 注册进去,然后业务代码里通过 ApiClient.instance.dio.post(...) 调用即可。这里的思路和普通 Flutter 项目完全一致,OpenHarmony 上不需要任何特殊处理。
举个例子,在应用启动时初始化:
dart复制void main() {
WidgetsFlutterBinding.ensureInitialized();
ApiClient.instance.init();
runApp(const MyApp());
}
然后在任意页面发请求:
dart复制final response = await ApiClient.instance.dio.get('/user/profile');
只要 Debug 模式,控制台就会自动输出完整请求日志。
4.3 结合 hdc 和 hilog 在 OpenHarmony 真机上查看日志
在 OpenHarmony 真机上调试时,Flutter 的 debugPrint 输出会进入系统日志系统(hilog)。你可以用 hdc 把日志拉出来看:
bash复制hdc shell hilog | grep -i "\[API\]"
如果 logPrint 里加了一个 [API] 前缀,那么 grep 一行就能过滤出所有网络请求日志,非常清晰。这个方法比在 IDE 里点开 Flutter 控制台更直接,尤其是在设备连不上 IDE、只能用命令行调试的时候。
有一点要注意,hilog 默认的日志缓冲区可能有限,如果日志量特别大,可以用 hdc shell hilog -G 4M 先扩容一下,再跑测试。这个细节虽然小,但在调高 maxWidth 或打印大响应体时,能避免日志被截断。
4.4 从日志中快速定位两类常见问题
我把实际项目中碰到的问题分成两类,日志排查法也不一样:
- 请求没发出去/连接超时:重点看请求行的 URL 和端口是不是正确,再看
connectTimeout是否设置得太小。日志里如果显示ConnectionTimeoutException,那基本是网络环境或域名解析问题,先 ping 一下域名确认网络通不通。 - 响应解析失败:看响应体的 JSON 结构是否符合预期。比如字段名对不对、类型是不是 String 而不是 int。日志里能直接看到原始 JSON,对照一眼就能发现问题。
打个比方,日志就像一面镜子,它把你代码里看不见的运行时状态照出来。而 Pretty Dio Logger 这面镜子,把 HTTP 层的状态照得特别清楚。
5. 常见问题与排查技巧实录
5.1 日志不出来,或只出来一半
我见过很多人接入之后,第一个反应是:怎么没日志?
先检查三件事:
- 是否在
kDebugMode下运行?Release 模式默认不会打印。 - 是否在
logPrint里做了一些兼容性处理,但打成了别的输出级别?比如接了logger包,但logger的 level 是Level.off。 - 你的 Dio 实例是否真的挂载了拦截器?有时候项目里有多处创建 Dio 的地方,你只在某一处加了拦截器,另一处没加。
在 OpenHarmony 上,还有一个特有情况:Flutter 进程的 stdout 输出在某些设备上不会实时刷到 IPC 日志里。这时候用 hdc shell hilog | grep flutter 去过滤,如果还是看不到,可以试试在 logPrint 里强制写文件,或者用一个 debugPrint 包装并 flush。
5.2 中文乱码和超长内容截断
Flutter 控制台对中文的支持其实还可以,但 OpenHarmony 的 hilog 对 UTF-8 的处理不一定完美。如果响应体里全是中文,日志出来可能是一堆占位符。这时候我不建议改插件源码,而是换一种方式:在响应拦截器里主动打印关键字段,而不是依赖整个响应体的打印。
另外,maxWidth 和 maxLine 也会导致“看起来被截断了”。如果响应体是一个几万行的 JSON,maxLine: 3 确实会截断。但截断是为了不刷屏,看整体结构就够用了。如果你需要看完整响应,可以在排查时将 maxLine 临时调大,或者直接把响应体写入本地文件再查看。
5.3 日志里带了敏感信息怎么办
这是很多团队容易忽略的点。一旦你把日志系统接得太大意,登录密码、Token、手机号这些信息就可能出现在日志聚合系统里,造成安全隐患。
我的处理原则是:
- 生产环境(Release)一律不挂载 Pretty Dio Logger
- Debug 环境下,对包含敏感字段的请求体做脱敏处理
- 使用
filter参数跳过登录、支付等敏感接口
如果团队有日志平台,把经过脱敏的请求日志上报,用于远程定位问题,那也要严格限制访问权限。
5.4 在 OpenHarmony 上编译报错,提示找不到插件
pretty_dio_logger 是纯 Dart 包,通常不会出现“找不到原生实现”的问题。但如果你读到类似“MissingPluginException”的报错,那大概率不是这个插件的问题,而是其他某个插件不支持 OpenHarmony。排查的时候,可以用 flutter build apk 或 hvigor 的编译日志,定位到具体是哪个插件在注册原生端时失败。
还有一个常见情况:项目里多个插件用了同一个原生类名或资源名,导致编译冲突。这时候检查一下 oh-package.json5 里的依赖,看看是不是混入了一些只支持 Android/iOS 的库。
5.5 一个很实用的小技巧:把耗时打印出来
在 responseBody 之后,你会发现 Pretty Dio Logger 已经自动打印了请求耗时(比如 0.5s)。这一个小功能在排查性能问题时特别有价值。我经常用它判断:
- 某个接口是不是太慢,需要做缓存或并发优化
- 是不是某些接口在弱网环境下超时,进而影响到页面加载体验
你完全不用自己埋点统计耗时,因为它帮你算好了。
6. 写在最后的一些个人体会
在我把 Flutter 项目迁移到 OpenHarmony 的过程中,感受最深的一点是:很多原本以为是“平台适配难题”的东西,其实只要选对了生态里的纯 Dart 插件,就能避免掉大多数兼容性问题。Pretty Dio Logger 就是这类工具的代表——它没有炫酷的 UI,没有花哨的功能,但它在开发调试时带来的效率提升,是实打实的。你不需要再怀疑“这个请求到底干了什么”,因为日志已经明明白白地写在那里。
另外,我个人的习惯是:用日志不是为了“打出来好看”,而是为了养成“先看日志再猜原因”的调试思路。遇到网络问题,打开日志看请求、看响应、看耗时、看错误,大部分问题都能在几分钟内定位。而 Pretty Dio Logger 正是帮你把这条链路拉通的那个工具。
如果你也正在 OpenHarmony 上做 Flutter 开发,建议从一个小项目开始,先接好日志链路,再慢慢铺开业务功能。网络监控这块打好底子,后面排查问题会轻松很多。
