Flutter Platform Channel 的 await 陷阱:为什么加与不加相差 100ms?

7 阅读2分钟

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