最近在把公司 Flutter 端往 OpenHarmony 上迁移时,我遇到的最头疼的问题不是页面能不能跑起来,而是网络层一旦出问题,根本不知道请求到底发出去没有、响应回来了什么、状态码是多少。真机调试不像浏览器有 F12 面板,也不可能每个开发人员都熟练配置抓包工具。后来我把 Dio 的请求日志拦截器 Pretty Dio Logger 接到项目里,配合 hdc 工具看日志,整个网络请求监控的效率直接起飞。这篇文章就把我在 Flutter for OpenHarmony 上集成 Pretty Dio Logger 的完整过程、参数调优和踩坑记录分享出来,给同样在做 OpenHarmony 适配的朋友一个可以直接抄的作业。
1. 项目背景与方案选型:网络请求监控为什么选了 Pretty Dio Logger
1.1 Flutter 迁移到 OpenHarmony 后,调试网络请求的痛点
先说背景。OpenHarmony 的适配不是把 APK 装上去就行,Flutter 应用要跑在 OpenHarmony 设备上,需要用到 OpenHarmony SIG 组维护的 Flutter 适配 SDK,构建产物是 HAP 包,通过 hdc 命令部署到开发板或者真机上。我在 RK3568 开发板上调试时就发现,网络请求一旦出问题,排查手段非常有限。
首先是没法直接用 Charles、Fiddler 这类工具抓包,尤其是走 HTTPS 的请求,还得在设备上装证书、配代理。开发板本身存储和性能都有限,频繁装证书、改 Wi-Fi 代理非常折腾。其次是 Flutter 层自带的 debugPrint 打印,默认只输出 1000 字符左右的内容,超长就会被截断,JSON 响应体稍微一长就看不全,更别说格式化了。第三个痛点是日志和时间线对不上,尤其是并发请求多的时候,一个页面同时发三四个请求,日志混在一起,根本分不清哪条是哪个接口回的。
我也试过自己写一个 Dio 拦截器来打印日志,但写着写着就变成了一个半吊子工具,要处理的边界情况越来越多:请求头要不要打、响应体太长怎么截断、二进制流内容会不会把控制台刷爆、日志里带敏感信息怎么办。与其造这个轮子,不如直接用现成的 Pretty Dio Logger,它本身就是专门为 Dio 设计的一个日志拦截器,输出格式经过长期打磨,比我自己写的要规范得多。
1.2 Pretty Dio Logger 能帮你做什么
Pretty Dio Logger 说简单点,就是给 Dio 网络库加一个拦截器,在请求发出之前和响应回来之后自动打印格式化的日志。它最明显的优点是输出自带颜色和信息分级,虽然不是每次都必须在终端看颜色,但请求方法、URL、请求头、请求体、响应状态码、响应耗时、响应体这些关键信息,全都会按固定结构打印出来,查找问题的时候一眼就能定位到关键行。
它内部是依赖 Dio 的拦截器机制实现的,本质上就是 Interceptor,所以接入成本几乎为零。你不需要改业务代码里的任何请求调用,只需要在创建 Dio 实例的时候把它挂到 interceptors 列表里,后面的所有请求和响应都会自动被记录。对于我这种维护老项目、不想大规模改动网络层的人来说,这一点非常友好。
另外,它支持按需开关。比如我不关心响应头,只关心响应体,那就在构造参数里把 responseHeader 设成 false。再比如调试阶段想看完整请求体,但生产环境绝对不能打敏感信息,就可以用 canLog 或者 logPrint 做环境判断。这套灵活度比很多团队自己封装的日志拦截器要完善得多。
1.3 为什么不用抓包工具而是选拦截器
有人可能会问,抓包工具不是更通用吗?这里有个关键区别:抓包工具是独立于应用的,能抓所有流量,但抓不到应用内部已经加密或者走了非 HTTP 通道的数据;而拦截器是在应用进程内部工作的,能看到业务代码这一层的完整上下文。对于 Flutter 应用来说,很多请求是经过 Dio 封装后发出的,响应回来之后还会在拦截器里做统一状态码处理、token 刷新、错误上报等逻辑,这些在抓包工具里是看不到的。
所以我的做法是两层配合:底层网络抓包用工具,应用层日志用拦截器。Pretty Dio Logger 负责把 Dio 这一层的数据完整记录下来,抓包工具负责验证 DNS、TLS 握手、具体报文。在日常开发调试中,90% 以上的问题其实通过应用层日志就能定位,根本不用走到抓包那一步。
我还对比过其他几个方案,比如 dio_logger、dio_interceptor 之类的插件,但 Pretty Dio Logger 的参数设计和输出排版最成熟,更新频率也比较稳定。以下是几个常见方案的简单对比:
| 方案 | 接入工作量 | 日志格式 | 参数灵活度 | OpenHarmony 兼容性 |
|---|---|---|---|---|
| 自写拦截器 | 高 | 自定义,质量难保证 | 高 | 无额外依赖,纯 Dart 即可 |
| dio_logger | 低 | 较弱,输出较简陋 | 一般 | 纯 Dart,可用 |
| Pretty Dio Logger | 极低 | 格式化完善,信息分级清晰 | 高 | 纯 Dart,可用 |
最后我选了 Pretty Dio Logger,理由非常直接:它不依赖任何平台原生代码,在 OpenHarmony 的 Flutter 环境里不用做额外适配,这是先决条件。在此基础上,它的输出格式、参数控制和社区活跃度都符合预期。
2. Flutter for OpenHarmony 环境搭建与依赖接入
2.1 搭建可运行 ohos 工程的 Flutter 开发环境
要跑 Flutter for OpenHarmony,首先要有一台装好 Flutter SDK 的电脑。我用的是 mac,所以环境变量配置相对简单。需要注意的是,OpenHarmony 的 Flutter 适配 SDK 虽然 API 和官方 Flutter 基本对齐,但版本节奏是独立的,一定要通过 OpenHarmony SIG 的文档去拉取对应的 flutter sdk,不要直接用社区版 Flutter 的官方渠道,否则flutter create --platforms ohos的时候会提示平台不支持。
第二步是安装 DevEco Studio 和 OpenHarmony SDK。这一步很多朋友容易卡住,因为我一开始也找不到 SDK 路径在哪。装完 DevEco Studio 之后,需要在 Preferences -> SDK Manager 里确认 OpenHarmony SDK 已经下载,并且记住路径。这个路径后面要配到 FLUTTER_OHOS_HOME 或者 .bash_profile /.zshrc 里,否则 flutter 命令找不到 ohos 的编译工具链。
还需要把 hdc 工具配置到 PATH 环境变量里。hdc 是 OpenHarmony 的命令行调试工具,作用和 adb 之于 Android 类似。打开终端输入 hdc -v 能输出版本号,就说明工具链基本通了。用数据线把 RK3568、RK3588 这类开发板或者真机连到电脑后,输入 hdc list targets 能看到设备序列号,说明连接正常。
这里顺便说一下,很多人在安装阶段遇到 flutter doctor 报错,不要太焦虑。flutter doctor 主要是给 Android/iOS 用的,对 ohos 支持情况的检查并不完整,只要 DevEco Studio 能创建 HarmonyOS 工程,hdc 能连上设备,你的 ohos 工具链基本就 OK 了。我的经验是,以“能否成功构建出 HAP 包”作为环境合格的标准,而不是以 flutter doctor 全绿为标准。
2.2 创建或改造 Flutter 工程支持 OpenHarmony
假设你已经有了一个 Flutter 项目,想给它加上 OpenHarmony 平台支持。在正确配置环境下,只需要在项目根目录执行:
flutter create --platforms=ohos .这个命令会生成 ohos 目录以及对应的工程配置文件。如果在旧版本 Flutter 上执行,发现没有 ohos 平台选项,八成是你拉的不是 OpenHarmony 适配版 SDK,回 2.1 重新确认一下工具链来源。
对于新项目,可以直接用:
flutter create --platforms=ohos --org com.example --project-name my_app my_app项目生成之后,在 device 上选择 OpenHarmony 设备,执行 flutter run 就能跑起来。有一点要注意:如果你的电脑上同时连着 Android 设备和 OpenHarmony 设备,flutter run 可能会默认选 Android。我记得第一次跑的时候没注意,日志怎么都不对,后来发现是跑到了旁边的 Android 手机上。最好只连一个设备,或者用 hdc 把不需要的设备断开。
另外,如果你之前构建过 Android 端,ohos 目录和 android 目录互不干扰,两者可以共存。构建 OpenHarmony 产物时,flutter build hap 会生成 HAP 包,这个包的路径一般在 build/ohos 下,可以用 hdc app install 安装到设备上。如果遇到编译后磁盘占用大的问题,可以删除 build 目录下的中间产物重新构建,OpenHarmony 编译产生的文件很多是可以重复生成的,不需要手动保留。
2.3 引入 dio 与 pretty_dio_logger 依赖
OpenHarmony 支持的 Flutter 工程里,pubspec.yaml 的写法和官方 Flutter 基本一致。依赖添加如下:
dependencies: flutter: sdk: flutter dio: ^5.4.0 pretty_dio_logger: ^1.3.1指定版本的时候需要注意,dio 5.x 和 dio 4.x 有些 API 不一样,比如超时时间的类型从 int 毫秒变成了 Duration 对象。如果你的项目是从 dio 4.x 升上来的,建议先统一到 5.x,再接入 Pretty Dio Logger,因为新版拦截器接口和超时配置都不太一样,混着写容易踩坑。
pretty_dio_logger 是纯 Dart 实现,不依赖任何平台通道,所以不需要在 OpenHarmony 侧做原生配置。执行 flutter pub get 之后,只要没有语法错误,这个包就可以直接用了。这也是我推荐它的原因之一:在 OpenHarmony 这种新平台上,能少一个平台相关依赖就少一个,否则哪天某个原生插件没有 ohos 实现,你就要自己去写平台通道。
3. Pretty Dio Logger 参数详解与进阶配置
3.1 最小可用配置:挂上拦截器就能看到日志
接入的核心代码非常少,两步就走完了。第一步创建 Dio 实例,第二步挂上拦截器:
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: const Duration(seconds: 10), receiveTimeout: const Duration(seconds: 10), ), ); dio.interceptors.add( PrettyDioLogger( requestHeader: true, requestBody: true, responseHeader: true, responseBody: true, error: true, ), ); return dio; }这样配置完成之后,项目里所有通过这个 Dio 实例发出的请求,都会在终端打印对应的日志。注意一定是用同一个实例,如果你在多个地方分别创建 Dio 实例,拦截器没挂上的那部分请求依然不会有日志输出。
最小配置跑通之后,我建议你先看一次完整日志长什么样,确认格式满足需求,再根据实际场景去调参数。这个确认过程很重要,因为不同项目的接口返回差异很大:有的接口返回几 KB 的 JSON,有的接口返回二进制流,还有的接口只有状态码没有响应体,这些场景对日志打印的要求是完全不同的。
3.2 核心参数逐个拆解,按需开关
Pretty Dio Logger 的参数,每个都对应一类日志内容。我把常用的参数整理成了表格,实际配置时照着这个表来选:
| 参数 | 默认值 | 控制内容 | 我的建议 |
|---|---|---|---|
| requestHeader | true | 是否打印请求头 | 调试期开,排查鉴权问题很有用 |
| requestBody | true | 是否打印请求体 | 建议开,POST 请求参数一目了然 |
| responseHeader | true | 是否打印响应头 | 默认开,关注 set-cookie 和分页字段时用 |
| responseBody | true | 是否打印响应体 | 核心参数,调试期基本必开 |
| error | true | 是否打印错误信息 | 建议开,DioException 堆栈很有用 |
| compact | false | 是否压缩打印格式 | 真机终端建议 true,开发板性能有限 |
| maxWidth | 90 | 每行最大宽度 | 根据终端宽度调,过长会换行乱 |
| canLog | null | 是否允许打印的全局开关 | 生产环境设置 false |
| logPrint | null | 自定义日志输出函数 | 可用来脱敏、写入文件、上报日志系统 |
这里重点说一下 compact 和 maxWidth。compact 默认为 false,此时日志会打印得非常详细,但会有大量空行和装饰性字符,在电脑终端上看很漂亮。但 OpenHarmony 开发板的串口控制台或者 hdc shell 里查看时,宽屏支持往往不好,装饰性字符会把界面打得非常乱。我实测在 RK3568 开发板上调试时,compact 设为 true 之后,日志行数少了将近一半,定位问题的效率明显提升。
maxWidth 控制的是单行输出最大宽度,单位是字符数。默认 90 比较适合 IDE 自带的终端,但如果你用的是 256 色终端或者把它接到 CI 日志系统,建议适当调整。太长会换行,太短又会把 URL 和 JSON 挤成很多行。命令行窗口可以临时拉伸的话,我一般设置成 120 到 160,一行能放下更多信息。
canLog 是一个逻辑开关,示例:
PrettyDioLogger( canLog: () => kDebugMode, )注意 canLog 不是普通 bool,而是一个返回 bool 的方法,每次打印的时候会调用一次。如果你希望日志系统里可以动态控制某类请求是否打印,这个方法非常有用。我之前做过一个实验,给 canLog 传一个返回值由全局开关控制的方法,测试阶段直接改全局变量就能所有页面日志全开,不用重新发版。
logPrint 是这个插件最灵活的地方,默认是 debugPrint,会走 Flutter 的 debug 输出通道。如果你想把日志同时输出到终端和文件,就可以覆盖它:
PrettyDioLogger( logPrint: (log) { debugPrint(log); // 自己再把 log 写入本地文件 }, )这里有一个细节:logPrint 的入参类型是 String?,你把它打印出来之前要注意判空,否则有些环境下会因为 null 导致格式化占位符异常。我的习惯是直接在回调里写if (log == null) return;。
3.3 进阶用法:环境区分、脱敏与日志落盘
实际项目中,开发环境和生产环境往往共用一套代码,区别只是 baseUrl 不同,这时候日志打印策略也应该是分开的。生产环境绝对不能把登录接口的账号密码明文打到日志里,更不能把 token 写到默认输出流。
我的做法是在初始化 Dio 时,根据当前环境传入不同的 PrettyDioLogger 配置:
PrettyDioLogger _buildLogger() { final isProd = const bool.fromEnvironment('dart.vm.product'); final logger = PrettyDioLogger( compact: true, maxWidth: 120, canLog: () => !isProd, ); if (isProd) { return logger; } // debug 环境额外做脱敏 logger.logPrint = (log) { if (log == null) return; var safe = log.replaceAll(RegExp(r'(?<=token=)[^&\s]+'), '***'); safe = safe.replaceAll(RegExp(r'(?<="password":")[^"]+'), '***'); debugPrint(safe); }; return logger; }这个脱敏思路可能看起来简单,但在实际项目里非常实用。请求体如果是一个 JSON 字符串,密码字段就可能以 "password":"123456" 的形式出现,正则一替换,日志里就看不到明文了。Authorization 头如果是以 Bearer token 的形式存在,要把 token 字段也替换掉。这些信息一旦通过 CI 日志系统泄漏出去,后果很严重,所以我在日志插件里最重视的就是脱敏。
日志落盘这件事,OpenHarmony 设备的存储路径和 Android 不一样,建议用 path_provider 的 getApplicationDocumentsDirectory 来获取应用私有目录,然后往里面写日志文件。不要直接写绝对路径,不同设备存储结构不一样,容易踩坑。
4. 真机调试实录:用 hdc 和 hilog 排查网络问题
4.1 连接 OpenHarmony 设备并确认系统信息
在开发板上跑起 Flutter 应用之后,我看日志一般有两种方式。第一种是在电脑终端直接看 flutter run 的输出,这种方式最直观,日志会实时滚动,还带颜色。第二种是通过 hdc shell 进到设备里,用 hilog 命令过滤日志,适合应用已经安装运行、但不方便重新跑 flutter run 的场景。
如果你的应用是装到设备上独立运行的,建议先确认设备系统版本和型号,避免日志协议对不上。常用命令:
hdc shell param get | grep -i const.product.name hdc shell param get | grep -i const.product.version第一条命令可以查看产品名,第二条可以查看版本号。这是排查设备型号差异最直接的方式。之前我在 RK3568 和 RK3588 两块开发板上跑同一个 Flutter 应用,表现完全不一样,一查产品名才发现系统的图形栈版本有差异。
如果要看设备上已经安装了哪些应用,用:
hdc shell bm list | grep your.package.namebm list 会列出所有 bundle 名,如果你安装的 HAP 包没有出现在列表里,说明没装成功,那日志里当然看不到任何内容。设备标识信息可以通过hdc shell param get const.product.devudid之类的属性获取,不同系统版本字段名略有差异,不确定的时候就多 grep 几个关键字。
4.2 一次真实请求的日志解读
下面这段是 Pretty Dio Logger 在 compact: true 模式下的一段输出,我模拟了一个用户登录接口的调试现场:
┌──────────────────────────────────────────────────────────────── │ ╭ GET http://10.0.0.2:8080/api/v1/login │ ├ headers: │ │ Authorization: Basic xxxxxx │ ├ queryParameters: │ │ username: admin │ ╰┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄ │ ╭ GET http://10.0.0.2:8080/api/v1/login │ ├ statusCode: 200 │ ├ took: 63ms │ ├ headers: │ │ content-type: application/json │ ├ body: │ │ {"code":0,"token":"eyJhbGci..."} ╰┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄第一次看到这个输出,可能觉得装饰字符有点多,但仔细看的话,它的结构是非常合理的。上面是请求部分,包含方法、URL、请求头和查询参数;下面是响应部分,包含状态码、耗时、响应头和响应体。我把这些信息用来定位问题时,最常用的是状态码和耗时。
比如状态码变成 401,我第一步就去检查请求头的 Authorization 是不是被成功带上了,如果是,再去看 baseUrl 是否指向了正确的环境。比如 took 显示 3 秒,响应体还没返回,那就是网络层超时,可能是开发板 Wi-Fi 信号不好,也可能是服务端接口本身慢。这种定位思路比用抓包工具去一层层看报文要快得多。
还有一个小技巧:如果某个接口返回的 JSON 结构复杂,我会先把响应体复制到本地 JSON 解析工具里格式化一遍,确认字段层级,再对着代码里的模型类检查字段名是否匹配。Flutter 端的 JSON 解析错误往往不是语法错误,而是字段名对不上,看了 Pretty Dio Logger 打印的响应体,基本能一眼看出问题。
4.3 拦截器顺序与业务错误处理的配合
Dio 的拦截器是有顺序的,添加顺序就是执行顺序。请求阶段,先添加的拦截器先执行;响应阶段,先添加的拦截器后执行。这个顺序会直接影响你看到的日志内容。
我的建议是把 PrettyDioLogger 放在拦截器列表的最后一个,也就是最后打印日志:
dio.interceptors.add(AuthInterceptor()); dio.interceptors.add(ErrorInterceptor()); dio.interceptors.add(PrettyDioLogger());这样做的原因是:日志拦截器要记录的是“最终实际发出的请求”和“最终拿到的响应”。如果其他拦截器在日志拦截器之后执行,比如 AuthInterceptor 在最后补充了 token,日志里就缺少最终的请求头,看起来会不明所以。
业务错误处理的逻辑我建议放在日志拦截器之前,这样日志里错误信息是原始响应。如果错误处理器把 DioException 转成了业务错误码,日志打印的就是转换后的错误对象,原始的 500 状态码和响应体反而被吞掉了,排查问题时信息会不完整。
另外,在 OpenHarmony 开发板上,性能比较有限,如果响应体特别大,打印 JSON 本身就会消耗一定时间。建议在调试大响应接口时,打开 compact 模式,并且在 logPrint 里做一次长度判断,超过阈值就只打印前 500 个字符加省略号。这种“限制日志长度”的思路,能避免大量日志输出导致 UI 卡顿。
5. 常见问题与避坑清单
5.1 日志看不见、格式乱、卡顿怎么排查
先列一个高频问题速查表,都是我实际遇到过的:
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| 完全没有日志输出 | 拦截器没挂到实例上 | 确认请求确实走的是挂了拦截器的 Dio 实例 |
| 只有 debug 模式才有日志 | canLog 或 release 配置限制 | 检查 canLog 返回值,生产环境本来就不该打 |
| 日志被截断,JSON 看不全 | debugPrint 默认限制 | 覆盖 logPrint,自己分段打印或写入文件 |
| 控制台显示乱码/换行混乱 | 终端宽度不足或 maxWidth 不合适 | 调整 maxWidth,开启 compact |
| 日志很多但卡顿明显 | 输出量太大阻塞 UI | 限制日志长度,避免打印超大响应体 |
| 500 错误状态码没有打印 | 错误被其他拦截器提前处理 | 调整拦截器顺序,日志放在最后 |
我自己踩过最隐蔽的一个坑是:在 OpenHarmony 设备上运行应用时,flutter run 的输出正常,但断开 USB 再跑的时候,hilog 里怎么都看不到日志。后来发现这跟 Flutter 的日志通道有关,应用通过 hilog 输出的 tag 是 Flutter,不一定等于应用的 bundle 名。查日志的时候要用hdc shell hilog | grep Flutter去过滤,而不是直接 grep 包名。
还有一个和网络请求本身无关但容易影响判断的坑:如果开发板系统时间不对,日志里的时间戳会是乱的,排查超时问题时会得到错误结论。建议连接开发板后先确认时间,用hdc shell date检查一下,不准就先同步时间。
5.2 Flutter 插件在 OpenHarmony 上的兼容性问题
先说结论:纯 Dart 实现的包,比如 dio、pretty_dio_logger、path_provider 的 Dart 侧接口,在 OpenHarmony 的 Flutter 环境里通常都能直接跑通。但凡是依赖了 Android 原生代码的插件,比如某些地图 SDK、支付 SDK、push SDK,如果 OpenHarmony 侧没有对应的原生实现,就会报平台通道异常。
我们项目里就遇到过类似问题,Flutter 端接了某个地图组件,在 Android 上运行正常,但跑在 OpenHarmony 设备上时,日志里出现一大段类似 MethodChannel 找不到实现或者调用失败的错误。这时候用 Pretty Dio Logger 是看不到的,因为它只关注 HTTP 层。我的排查思路是:先确认该插件是否有 ohos 适配版,如果没有,就要找 OpenHarmony 原生 SDK 来写平台通道。
这其实也解释了为什么社区里有那么多关于“flutter 如何接入高德”这类问题,本质都是第三方 SDK 的 OpenHarmony 适配问题。网络日志打印在这种场景下只能看到应用层的 HTTP 请求,SDK 内部的私有加密请求是看不到的,所以不要指望 Pretty Dio Logger 能解决所有问题。
另外,如果遇到类似you are applying flutter's main gradle plugin imperatively这种报错,说明你在构建时把 Android 的 Gradle 配置经验直接生搬硬套到了 OpenHarmony 工程上。OpenHarmony 工程的构建体系是 hvigor,和 Gradle 不是一回事。遇到构建报错先看构建系统是不是对的,别拿着 Android 的经验去处理 ohos 目录。
5.3 OpenHarmony 开发中的几个高频坑,别重复踩
除了日志插件本身,我还想顺手分享几个 OpenHarmony Flutter 开发中容易被绊倒的地方。这些不一定都和网络请求相关,但都会影响调试效率。
第一个是 USB 和 hdc 连接问题。开发板有时候插上 USB 之后 hdc list targets 看不到设备,大概率是 USB 调试权限没打开,或者驱动没装好。可以试试hdc kill再hdc start。OpenHarmony 对 USB 设备的管理用到了 usbmanager 和 libusb,这些是设备侧的原生能力,跟 Flutter 应用层的调试工具链没关系,但如果你在做 USB 相关的业务,需要单独去了解。
第二个是设备标识获取。很多 App 需要拿设备的唯一标识来做埋点,OpenHarmony 上获取 devudid 和 serial 的接口和 Android 的 Build.SERIAL 不一样,不要照搬 Android 的写法。这个在网上能搜到很多资料,但核心原则是:优先用官方文档提供的接口,别依赖第三方封装。
第三个是定制系统相关的问题。比如有人想修改 const.product.name 来定制系统版本号,这属于系统编译层面的定制,做完之后一定要重新构建系统镜像,不是改一个普通配置文件就生效的。这类问题和应用层日志调试没关系,但在团队协作时容易混淆,我在集成日志插件时就收到过一条“为什么系统版本显示不对”的错误,排查半天才发现是测试同事改错了系统镜像。
第四个是 Flutter 开发中常见的 UI 问题,比如底部弹窗里有 TextField,弹窗被键盘顶起或者输入框被遮挡。这类问题在 OpenHarmony 上一样会遇到,和在 Android 上处理方式类似。但在开发板上测试时,由于屏幕分辨率可能比较特殊,建议多测几种键盘输入场景,否则接口调试通过,UI 交互又出问题,又要回头排查。
写在最后
我在实际调试中最大的体会是,工具链越简单越好。Pretty Dio Logger 本身不复杂,但它能把网络请求这一层的信息透明化,让我不用猜测请求到底长什么样,而是直接看到请求、响应的全貌。踩过几次坑之后,我现在每接一个新平台,第一件事就是把日志体系搭好,网络层、页面生命周期、平台通道都做到有日志可查,后面再排查问题就会轻松很多。
最后再分享一个小技巧:把创建 Dio 的逻辑单独抽成一个 factory,统一在里面挂拦截器,全局只保留这一个入口。这样不管后续换日志插件、加鉴权逻辑,还是改动超时配置,都只需要改一个文件。配合环境变量和脱敏规则,这个网络层可以稳定用很久。