基于IoT,Flutter与硬件结合探索
如果无法正常显示,请先停止浏览器的去广告插件。
1. 基于IoT,Flutter与硬件结合探索
介绍关于高频耗时任务的解决方案
于桐 (Yutong)
2020年初加入字节,供职于字节对公教育业务,
入职以来基于Flutter 进行了多个业务方向探索,
现基于Flutter主攻进校业务场景开发。
2. 目录
• 1.团队框架现状介绍
• 2.高频耗时任务解决方案
3. 1.1 工程框架-组件化设
- 字节有完善的组件发布平台,加速了组件化开发。
计
- 不同组件不同git仓库维护,通过pubspec.yaml
依赖,进行工程隔离,进行解耦,并提高复用性。
- 基于Flutter跨平台特性,目前大量组件被团队内
多个业务复用,包括双端平台。
4. 1.2 页面框架-MvRx 设
计
• 页面状态管理框架选型,最后采用GetX 开源库,基于GetX具有上手容易、代
码理解成本低、使用灵活的特点,这里只使用其中的状态管理响应式能力。
• 基于 GetX 响应式能力进行 Flutter 版 MvRx 设计
5. 1.3 驱动框架(1)
结合状态机,事件驱动框架设计
• 进校业务背景下,更多基于硬件设备进行业务探索,发现硬件设备通常是事件驱动模式,例如
扫描仪,基于扫描事件来驱动业务逻辑变化,视图转场。
• 我们团队将事件驱动提升到框架层的高度进行设计,事件驱动框架对多业务模块负责,并结合
状态机,进行状态预测/分发,并将硬件事件与具体业务逻辑分离。
6. 1.3 驱动框架(2)
• 使用基于Service Locator模式的
EkGet,进行解耦。
• 通过EkGet获取事件驱动机相关实
例。
• 事件驱动机内部使用 RxDart进行
数据处理,基于RxDart的
transform、map等进行数据操作,
并实现硬件设备的事件/状态订阅
分发。
7. 2.1高频耗时Task的实践&方案探
索
• 进校业务迭代探索发现:
• 普遍存在生产消费模式,生产者多是高频工作的硬件设备,而对应的消费方需要依赖实际设
备性能、网络情况 。
• 实际上学校设备性能低、网络差是普遍现象。经常出现消费方消费速度慢于生产的速度,因
为耗时任务堆积 而出现OOM、ANR问题。
• 基于该问题,我们团队提供了3种解决方案
1. task scheduler
2. task pipeline
3. isolate pool
8. 2.2高频耗时Task的解决方案-task
scheduler
• 我们的业务需求:
• 需要一个任务缓存能力,支持一定的背压,并且支持任务调度执行
• 具备基本的任务管理能力,如添加、删除、执行等
• 能够承担高耗时的任务场景
• 前期我们进行了普遍的调研,但是没有找到合适的能力,如调研了像Dart 提供
SchedulerBinding.scheduleTask,该方法添加的Task是在帧之间按照优先级顺序进行
执行,并且Task 只用于几毫秒的耗时场景,同时不支持的多Task缓存能力。
9. 2.2高频耗时Task的解决方案-task
scheduler
• Task scheduler 任务调度器
• 特点:
• 任务调度器中的task 是存放在内部的缓存队列中。
• 支持cancel、remove 、callback 、backpressure等基本的能力。
• 任务执行是从队头开始,执行完当前任务后通过调度器自动执行下一个任务。
• 通过 execute 触发任务执行
10. 2.2高频耗时Task的解决方案-task
scheduler
• 但是在业务迭代中也遇到新的问题:
• 任务可能是批量添加,第一批任务和第二批任务添加的时机可能存在较长的时间间隔
• 第一批任务执行完毕后,因为没有新任务添加,任务调度器中止运行。
• 第二批任务添加时,只能通过 execute 重新触发执行,即意味着业务层要感知到每一批次任务
的添加时机。这在业务逻辑上会增加了一定的复杂度。
11. 2.3高频耗时Task的解决方案-task
pipeline
12. 2.3高频耗时Task的解决方案-task
pipeline
• Task pipeline, 任务管道
• 特点:
• 涵盖了task scheduler 对应的特点
• 但是无需主动调用 execute进行执行。
• 当管道中添加task时,开始执行,任务执行完毕后,如果管道中有其他task,则会执
行下一个,直到没有新task存在。
• 当管道中没有task时,暂停执行,但是管道不会被关闭,等待添加新task 来重新触
发执行。
13. 2.3高频耗时Task的解决方案-task
pipeline
• 至此提供了 Task Scheduler 、Task Pipeline 解决了生产消费模式的任务缓存、任务调
度的问题。
• 但是未解决主线程的卡顿,以及提升任务执行速度的需求。
• 因此需要引入 isolate的能力,将耗时任务转移至子线程中执行。
14. 2.4高频耗时Task的解决方案-isolate
pool
• 前期我们也进行了普遍调研,但是没有找到合适的能力,如调研了Dart 提供compute,
其是使用新开isolate线程,来用于执行耗时任务的。但是也发现了一些问题:
• 当时基于Flutter 1.22.3-0.0.pre.91 调研,该版本compute 存在引用悬空风险。
(Flutter之后版本修复)
• 入参和回参类型是一样的,而实际业务上二者类型大概率不同。
• 只是将耗时任务放到新开线程中,在任务处理速度上没有明显提升。
• 因此希望有一个类似Java 线程池的能力,基于此设计了 isolate pool,内部提供了双开
isolate方案,真正实现多线程并发,提高了任务执行速度,降低页面卡顿。
15. 2.4高频耗时Task的解决方案-isolate pool
·
提供Flutter版线程池能力
16. 2.4高频耗时Task的解决方案-isolate
pool
• Isolate pool , isolate 池
• 特点:
• 基于 task pipeline 管理task,具有任务管道的特点。
• 包含2个isolate,实现双开线程提高任务执行速度。
• 每个isolate 有自己的状态切换。
• 内部有 isolate loop ,负责isolate 轮询调度,以及isolate状态管理。
• 至此在生产消费模式上,isolate pool 算是圆满的解决了问题。
17. 2.4高频耗时Task的解决方案-isolate
pool
• 但是使用时发现了一些新的问题:
• 我们考虑将 isolate pool 作为独仓组件化方式实现多项目复用,但是实践中遇到了阻
碍:
• isolate 的使用,需要调用相关的业务逻辑,而业务逻辑需要放在顶层函数或类的静
态方法(静态方法不能涉及外部数据),
• 而对于顶层函数、静态方法,在组件中无法以面向对象思想进行封装,dart 反射能
力没有开放。
• 如果将其 作为参数的方式传入到isolate pool 中,就变为 isolate pool 实例属性,
因为 isolate 内存隔离,isolate与isolate pool 处于不同线程中,处于不同内存,而
实际处理业务逻辑的isolate 无法调用在不同内存的isolate pool 所指向的实例属性。
最终组件内部还是无法感知业务逻辑,即无法知道并调用业务的顶层函数、静态方法。
18. 2.4高频耗时Task的解决方案-isolate
pool
• isolate pool 是否可以作为顶层函数使用?
• isolate pool 中,涉及使用 Task Pipeline 能力,用于任务管理;以及isolate loop
能力,对 isolate 调度,和 isolate状态管理。
• 针对isolate pool 缓存任务队列的管理,以及任务调度的行为,需要面向对象方式进
行设计。
• 基于此不适合作为顶层函数处理,因此需要探索其他的复用方式。
19. 2.4高频耗时Task的解决方案-isolate
pool
• 可复用方案调研
方案介绍 缺点
注解方式实现复用,在编译期间触发代码生
成 •代码调试成本高,不能使用 Dart的 reHot 热启动模式,即不能使
用just in time (JIT) 实时构建代码进行调试
•使用复杂,需要更多理解成本
方案二 依赖本地脚本,实现模板代码生成。
通过拷贝脚本方式复用 •业务变化的内容如果通过脚本传参的方式反而体验不好,效率很
低
•多项目复用,通过拷贝脚本实现,只是减少拷贝量,没有根本提
升复用性
方案三 开发IntelliJ IDEA Plugin,
读取特定后缀的json 配置文件,进行模板代
码生成 •plugin 发布流程复杂
方案一
20. 2.4高频耗时Task的解决方案-isolate
pool
• 解决方案
• 使用 IntelliJ IDEA Plugin 思路,实现一个 ek_isolate_gen idea plugin。(目前发布在字节公
司内部)
• 该 idea plugin,会根据特定json格式的配置文件内容,生成isolate pool 相关代码,实现轻
代码开发,并实现多项目复用。
21. 2.4高频耗时Task的解决方案-isolate
pool
• .isolate_gen 文件配置:
22. 2.4高频耗时Task的解决方案-isolate
pool
• 至此基于idea plugin 能力,较优雅的实现了 isolate pool 多项目间复用。
23. THANKS.
欢迎推荐简历or技术交流 yutong.baron@bytedance.com