在 Flutter 项目中,一旦涉及:
- 蓝牙 / 串口 / USB
- 机器人 / IoT / 设备 SDK
- 音视频 / 图像 / AI
- 系统能力 / 第三方原生库
你本质上就进入了一个领域:
👉 Flutter 插件通信架构设计
很多项目前期"能跑就行",
后期会必然遇到:
- 性能瓶颈
- 通信混乱
- 职责不清
- 插件难维护
- Flutter / 原生边界失控
这篇文章从架构视角,系统拆解:
Flutter 插件通信,到底哪些该走 Channel,哪些必须下沉 FFI?
一、Flutter 插件本质是什么?
一句话:
👉 Flutter 插件 = Dart 世界 与 原生世界 的"边界层"
它解决的不是 UI,而是:
- 运行时隔离
- 语言边界
- 内存边界
- 线程边界
所以插件设计,本质是:
👉 系统边界设计
二、通信方式全景图
Flutter 插件通信方式,只有两大类:
Flutter (Dart VM)
|
| Platform Channel ← 语义层 / 消息层
|
Native (Java/Kotlin/ObjC/Swift)
|
| FFI (dart:ffi) ← 内存层 / 调用层
|
Native C/C++ Library
三、Channel 层:语义通信(消息系统)
Channel 的定位:
👉 跨语言消息传递
👉 跨线程调度
👉 序列化通信
三种模型:
| 通道 | 架构层级 | 典型职责 |
|---|---|---|
| MethodChannel | 接口层 | 控制 / API |
| EventChannel | 事件层 | 状态 / 回调 |
| BasicMessageChannel | 传输层 | 数据流 / 协议 |
Channel 适合什么?
- 业务命令
- 状态通知
- 参数传递
- 小数据
- 低频通信
Channel 不适合什么?
- 视频帧
- 音频流
- AI tensor
- 大块内存
- 毫秒级实时系统
👉 Channel = 消息系统,不是数据通道。
四、FFI 层:能力直通(函数调用 + 内存共享)
FFI(dart:ffi)本质是:
👉 Dart 直接调用 C API
没有 Channel 的:
- 消息队列
- JSON 编解码
- 跨线程派发
而是:
- 直接函数调用
- 指针操作
- 共享内存
FFI 适合什么?
- 图像处理
- 视频编解码
- 音频处理
- AI 推理
- 算法库
- 硬件 SDK
FFI 不适合什么?
- 业务接口
- 生命周期管理
- 系统 API(权限、窗口、蓝牙)
- UI 事件
👉 FFI = 能力层
👉 Channel = 协议层
五、最稳定的企业级插件分层
一个成熟插件,几乎一定是三层:
Flutter UI
|
Flutter Plugin API(Dart 封装层)
|
---------------------------------
| Platform Channel 层 |
---------------------------------
|
Native Plugin 层(Kotlin/Swift)
|
---------------------------------
| FFI |
---------------------------------
|
Native Core / SDK / C++
六、经典设备型插件结构
Flutter
├── MethodChannel → connect / start / config
├── EventChannel → onState / onError
└── BasicMessage → data stream
Native Plugin
├── 生命周期
├── 线程模型
└── SDK 管理
Native Core (C/C++)
├── 协议栈
├── 驱动
├── 算法
└── 音视频/AI
七、Channel 与 FFI 的清晰边界
✅ 应该走 Channel 的:
- connect()
- start()
- stop()
- setConfig()
- onState
- onError
- onStatus
👉 "系统语义"
✅ 必须走 FFI 的:
- processFrame()
- decode()
- infer()
- pcmCallback()
- imageBuffer
- sensorStream
👉 "数据与能力"
八、性能边界(真实项目必踩)
Channel 的代价:
- 线程切换
- 内存拷贝
- 序列化
- 调度延迟
FFI 的代价:
- 指针安全
- 崩溃风险
- 内存泄漏
- 架构复杂
👉 所以最优解一定是:
控制上浮,数据下沉
九、设计铁律(非常重要)
🔹 1. Flutter 不参与实时闭环
控制权必须在 Native / C++。
🔹 2. Channel 只传"语义"
不要传 buffer。
🔹 3. Flutter 只做"结果展示"
不是数据处理中心。
🔹 4. 插件必须可替换
通信协议要稳定。
十、一个架构级结论
Flutter 插件不是"桥接代码",
而是一个系统边界层。
你不是在写插件,
你是在设计一套:
👉 跨语言系统通信架构。
终极总结
| 层 | 职责 |
|---|---|
| Flutter | UI / 状态 / 交互 |
| Channel | 语义通信 / 协议 |
| Native | 系统调度 / 生命周期 |
| FFI | 高性能能力层 |
| C/C++ | 实时系统 / 算法 / SDK |
这条边界一旦清楚,你的 Flutter 项目规模可以非常大,而不会乱。