Flutter Platform Channel 的 await 陷阱:为什么加与不加相差 100ms?
现象
调用同一个 Android 方法,仅因是否加 await,耗时差距巨大:
dart
// ❌ 耗时约 100ms
await platform.invokeMethod('updateText', text);
// ✅ 耗时不足 1ms
platform.invokeMethod('updateText', text);
Android 端即使是空实现,await 版本依然要等 100ms。这 100ms 耗费在哪里了?
原因:同步等待的是完整往返,而非方法执行
带 await 的完整流程
text
Flutter → 序列化 → 跨进程传输 → Android 执行 → 序列化结果 → 跨进程返回 → Flutter
↑ ↑
调用 恢复执行
|←—————————————————— 等待 ~100ms ——————————————————→|
await 等待的是从发起到收到回复的整个往返过程,包含:
- 参数序列化
- 跨进程 Binder 传输
- 线程切换(Flutter UI 线程 → Android 主线程)
- 方法执行(实际业务逻辑)
- 返回值序列化
- 跨进程回传
- 反序列化结果
其中 方法执行只占很小一部分(可能不到 1ms),其余都是通信开销。
不带 await 的流程
text
Flutter → 序列化 → 跨进程传输 → Android 执行
↑
立即返回(不等待任何结果)
|←— < 1ms —→|
不等待时,Flutter 只负责把消息发出去,不等回复,因此几乎无阻塞。
为什么 100ms 是常态?
- Binder 跨进程通信:Flutter 与 Android 运行在不同进程,通信依赖 Binder,每次往返有固定开销
- 线程调度:涉及多次线程切换
- 序列化/反序列化:
StandardMessageCodec需要编码解码 - Flutter 引擎消息队列:消息排队与处理需要时间
这些开销叠加,使得一次完整的 MethodChannel 往返稳定在 50–100ms 区间。
什么时候该用 await?
| 场景 | 是否用 await | 原因 |
|---|---|---|
| 需要返回值 | ✅ 必须用 | 不等待拿不到结果 |
| 需要确认操作完成 | ✅ 建议用 | 保证后续逻辑顺序 |
| 需要错误处理 | ✅ 建议用 | try-catch 需要等待结果 |
| UI 更新 | ❌ 不用 | 不需要确认,发完即走 |
| 日志/统计上报 | ❌ 不用 | 不关心结果 |
| 预加载/缓存 | ❌ 不用 | 后台执行即可 |
实践建议
对于 UI 更新这类不需要返回值的操作:
dart
// 直接调用,不等待
void updateText(String text) {
AndroidviewApi.updateText(text);
}
如需处理异常,用 catchError:
dart
AndroidviewApi.updateText(text).catchError((e) {
// 处理错误
});
如需在完成后执行某些操作,用 then:
dart
AndroidviewApi.updateText(text).then((_) {
// 更新完成后的操作
});
总结
await 加与不加的本质区别是:同步等待完整往返 vs 异步发送即返回。
100ms 不是业务代码慢,而是 Platform Channel 通信的固有往返延迟。理解这一点,就能在正确的场景做出正确的选择——不需要等待结果时,就不要 await。