这不是 Dio 本身的 bug,是 TCP 连接池 + Dio receiveTimeout 机制 共同导致的。
根本原因
锁屏后 TCP 连接进入"半开"状态
锁屏时,Android/鸿蒙会将无线电模块降频/休眠,已建立的 TCP 连接在内核层被丢弃,但 app 层的 socket 仍认为连接是活跃的。Dio 内部维护一个 HTTP keep-alive 连接池,解锁后新请求可能复用了这些 僵尸连接(stale connections)。
为什么大响应才有问题:
小响应:即使连接质量差,数据量小,几秒内就传完了
大响应:数据传输过程中网络恢复时会出现极慢的数据流(每隔几秒传几个字节),不会完全断,但也跑不完
为什么 receiveTimeout: 30s 没有兜底住:
Dio 5.x(你用的 5.7.0)的 receiveTimeout 是 每次收到 chunk 就重置计时器,不是请求总时长限制。只要数据还在以极低速率"滴水",timer 就一直被重置,永远不会触发超时。这是 Dio 的设计行为,不是 bug。
两个修复方案
方案一:恢复前台时销毁 Dio 实例(治本)
只需在 App 从后台唤醒时调用,强制清空连接池,下次请求必然走新 TCP 连接。
方案二:每个请求加总时长兜底(治标,防止极端情况)
方案一解决 90% 的场景(唤醒后发起新请求),但如果请求在锁屏过程中已经在飞了,还需要一个总时长 hard timeout: