做医疗可视化开发的朋友,多半见过这样的场景:屏幕上一条红色的动脉压力波线在跳动,旁边几根蓝色的静脉回流曲线安静地蜿蜒,患者监护仪上每个跳动的数字背后,都是一整套血流动力学模型。我这次要分享的,就是基于鸿蒙和 Flutter 构建的动静脉血动力学可视化系统。简单说,就是把动脉血和静脉血的压力、流速、流量这些实时参数,用红蓝两套视觉体系在平板和手机上画出来。项目名里的“红蓝之辨”不是文学比喻,而是整个 UI 设计的核心规则:动脉用红,静脉用蓝,不能混。文章会从方案选型、核心绘制逻辑、工程排坑三个层面逐步拆解。适合有 Flutter 基础、正在考虑鸿蒙适配,或者想做医疗、运动健康类可视化应用的开发者参考。
1. 项目解读与技术选型:为什么是鸿蒙加 Flutter
1.1 “红蓝之辨”到底要做什么
在血流动力学领域,动脉和静脉是两个完全不同的物理通道。动脉侧承载的是心脏泵血产生的高压脉动信号,收缩压、舒张压、平均动脉压、脉压差这些指标全部靠它;静脉侧则反映回流情况,中心静脉压、每搏输出量、血氧饱和度,都决定了患者循环状态的好坏。可视化系统的目标很直接:把这些原本只有监护仪屏幕上才能看懂的连续波形,在鸿蒙设备上以更清晰、更可交互的方式呈现出来。
我在项目启动前梳理过需求,核心场景有两个。一是 bedside 监控场景,护士站或者床旁终端需要实时显示动脉压力波形、静脉回流趋势,异常时弹窗提醒;二是科研分析场景,医生需要把一段历史波形放大、拖动、对比不同时间点的数值变化。这两种场景对画面的要求完全不同,前者偏向高实时性和醒目告警,后者偏向渲染精度和交互顺滑。于是“红蓝之辨”就细化成了三条设计约束:第一,动脉通道所有元素统一红色系,静脉通道统一蓝色系;第二,波形、标签、数值背景色都遵循这套约束,不允许出现第三种表达通道的颜色;第三,红蓝之外的颜色只用于告警和辅助信息,比如绿色表示正常、黄色表示警告。
如果你也打算做这类系统,我建议一开始就把“颜色语义”写进设计规范文档里,而不是边开发边定。因为医学可视化产品对颜色的准确性要求很高,动脉和静脉一旦在界面上产生歧义,那就是事故级别的 bug。
1.2 为什么不用纯血鸿蒙 UI 方案
这个问题几乎每个合作过的开发都会问。鸿蒙原生有 ArkUI 和 ArkTS,声明式语法很成熟,布局组件也能覆盖大部分界面场景,为什么还要绕一圈用 Flutter?
原因要从团队和项目的约束条件说起。我们这个项目并不是只面向鸿蒙一个平台,早期版本已经跑在 Android 和 iOS 上,医疗设备厂商不会因为你换了个操作系统就把硬件生态推倒重来。如果用 ArkUI 开发鸿蒙版,等于要维护三套界面代码:Android 一套、iOS 一套、鸿蒙一套。三套代码的波浪绘制逻辑、手势交互、颜色定义,想保持完全一致,成本非常高。
Flutter 的价值在于“一次绘制,到处运行”。它的渲染引擎是自绘的,同一个 CustomPainter 在 Android、iOS、鸿蒙上能用同一套 Dart 代码画出完全一致的波形。这对医疗可视化是刚需:同一张波形图,在 A 设备上是一个样子,在 B 设备上是另一个样子,那整个判断标准就乱了。加上 Flutter 的动画管线是统一的,真机上的 60FPS 表现基本可靠,这也是我最后坚持用它做渲染层的原因。
当然如果项目只在鸿蒙设备上跑,而且团队没有跨端历史包袱,那直接用 ArkUI 完全没问题。技术选型没有绝对的对错,只看约束条件。我们这里是被“跨端一致性”和“开发效率”两个指标强推到了 Flutter。
1.3 Flutter 在医学可视化中的优势
Flutter 在医学可视化领域有几个被低估的点。首先,自绘引擎对实时曲线非常友好。用原生组件拼曲线图,往往要依赖图表库,而图表库遇到高频数据刷新时容易产生卡顿;Flutter 的 CustomPaint 每帧只做路径更新,不触发组件树 diff,性能上天然适合波形绘制。
其次,Flutter 的插件生态覆盖了医疗设备常见的通信方式。我们对接的监护仪既有蓝牙低功耗,也有网口上的私有 TCP 协议,Flutter 生态里这两类插件都很成熟,不用为每个平台单独写桥接层。虽然鸿蒙适配阶段需要处理一些原生端的权限和接口差异,但整体上通信层的复用程度依然很高。
还有一个容易被忽视的点:无障碍和字体渲染。医疗场景里的医生年龄跨度大,对字体清晰度和对比度要求高。Flutter 的文本渲染走的是自己的 Skia/Impeller 管线,在字号缩放、字体加粗这些细节上表现稳定,不像有些 Web 套壳方案会出现模糊。这一点在做科研截图、写论文插图时非常加分。
1.4 整体架构与数据流
系统结构上,我把它分成了五层。
数据采集层负责从设备或者模拟器读原始数据。我们项目里大部分时间用的是模拟数据源,因为真机监护仪不是随时都有,但接口要提前设计成和真实设备一样。
数据解析层把不同厂商的协议统一成内部模型。这一步很关键,医疗设备厂商的协议五花八门,有的按字节流带校验位,有的走 JSON 包,不统一的话上层代码会写出一堆 if else。
缓冲与平滑层处理数据抖动。传感器数据天生有噪声,直接画到屏幕上波形会“毛”得厉害。我会在这里做滑动窗口均值、去毛刺和异常点剔除。
渲染层是 Flutter 的主场,负责波形、数值卡片、趋势图、报警
