作者:Young,转自公众号 "黑金之路"
背景:
Flutter 作为跨平台框架,当涉及到混合开发模式时,会遇到一个场景:Flutter 模块需要访问原生的场景,比如需要使用到定位、原生开发的用户资料等等,那么如何高效、简单的实现原生和 Flutter 的通信就是本篇的内容
目录:
-
Channel 简介
-
协议的定义
-
通信的设计
一、Channel 简介
Flutter channel 类结构
(1)BinaryMessenger:Platform 端与 Flutter 端通信的工具
(2)BinaryMessageHandler:消息处理的抽象层
(3)BasicMessage / Method / Event Channel
-
BasicMessageChannel:用于传递字符串和半结构化的信息,可持续通信,收到消息后可以回复此次消息
例如:
a)Native 将硬件信息陆续传递到 Flutter
b)Flutter 将从服务器获取的信息传递给 Native 加工,Native 处理完返回等
-
MethodChannel:一次性通信,如:Flutter 调用 Native 拍照等
-
EventChannel:用于事件型的通信,仅支持 native 到 Flutter 的单向传递,如:电量更新通知
举例我们混合开发的业务场景:
-
Flutter 请求 Native 的用户信息、登录 token、环境变量等基础属性
-
Flutter 通知 Native 打开无线传屏等需要调用 C++ so的功能
-
Flutter 通知打开 Native 之前已经实现的复杂业务模块
-
Native 通知 Flutter 更新某些 UI 状态
结合以上官方提供的三种 Channel 和封装统一通信模块的实际需求,选择采用BasicMessageChannel 作为通信层更为合适。
二、 协议的定义*
本处采用 JSON;大家可自定义,如Protobuffer、自定义协议等
| 字段 | 含义 |
|---|---|
| path | 类似host路径,响应的地址,例子:/native/common/log |
| id | 请求的唯一标识,用于同一个消息调用的区分 |
| metohd | 请求方式,request,需要回复数据,observer 不需要消息回应,response,针对request的回复 |
| data | 数据块 |
另外,metohd 的定义在调用链的降低了协议的可读性,但相对也会暴露一个问题:需要回复结果的请求怎么处理?但考虑我们实际中需要回包执行结果的业务场景比较少,相对来说选择了协议的可读性对多人的开发的团队收益更高。
如果遇到这种场景怎么解决?答案是采用多次交互实现,即多次协议的交互即可。
举例:
协议定义详细
三、通信的设计
核心:
- Native 接收到消息后,处理任务不能出现阻塞
- Native 处理任务需要异步,不能卡主线程,避免出现 ANR
- 发出的每一个消息,不会因为异常等原因被 “淹没”,确保每一个消息都必须回包
Flutter 业务到 Native 流程设计
(1) Flutter 业务从 Channel 模块发送数据协议
(2) 原生协议处理模块,接收到消息队列
(3) 消息工厂生产消息,输出对应的待处理结构体到待处理队列中
(4) 多线程异步分发给 Native 业务处理模块
(5) 消息超时监控,防止队列阻塞,一个必须回复的任务如果在限定/默认时间未处理完则自动以错误处理回复
(6) 步骤4处理结果切换到子线程存储在结果响应队列
(7) 消息工厂处理响应的结果,输出待回复的结构体
(8) 丢到待回复队列,返回给 Flutter Channel 模块
另外:Native 业务到 Flutter 思路一致