在这里插入图片描述

从一行 flutter create 到一个完整的鸿蒙心理健康应用——本文是对整个开发旅程的全面回顾。


在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

一、项目速览

维度 数据
代码行数 ~2000 行 Dart(13 个源文件)
页面数 4 个主页面 + 首页
核心依赖 2 个(hive_ce + hive_ce_flutter)
目标平台 HarmonyOS 6.1.0 (API 23)
网络权限 0
外部资源 0(全部程序化生成)
构建产物 ~15 MB(Release HAP)

二、架构决策回顾

决策 1:Hive CE → ✅ 正确

纯 Dart 的 Hive CE 替代需要原生 SQLite 的 sqflite。在鸿蒙上运行完美,零兼容性问题。写入性能比标准 Hive 慢 60%,但用户完全无感知。

教训:跨平台应用中,"纯 Dart"方案的长期价值远超短期性能。

决策 2:ChangeNotifier → ✅ 正确

不引入 Provider/Bloc/Riverpod,直接用 Flutter 内置的 ChangeNotifier。2 个数据源、5 个页面的规模下,原生方案完全胜任。

边界:如果页面超过 15 个或 Widget 嵌套超过 5 层,应该切换到 Provider。

决策 3:离线优先 → ✅ 正确

零网络权限,所有数据本地存储。AppGallery 审核零阻力,用户隐私信任度最高。

决策 4:程序化资源 → ✅ 正确

用 Dart 代码生成图标和音频。Git 仓库体积减小 350 倍,构建完全可复现,零版权风险。

决策 5:无音频播放 → ⚠️ 待改进

白噪音功能仅有视觉脉冲动画。等待 audioplayers_ohos 或类似方案成熟后接入。音频文件已生成好(WAV),只差播放器。


三、开发时间线与工作量分布

整个项目从零到 AppGallery 上架,实际开发周期约 8 周(业余时间,日均 2-3 小时)。以下是各阶段的时间分布估算:

阶段 时间占比 主要工作
环境搭建与鸿蒙适配 25% DevEco Studio 配置、Flutter 鸿蒙引擎编译、签名证书调试、Hive 迁移
核心功能开发 30% 情绪记录 CRUD、呼吸引导动画、白噪音视觉、MoodChart 柱状图
程序化资源生成 15% WAV 编码器、PNG 图标生成器、噪声合成算法、花瓣纹理渲染
测试与调试 10% 单元测试、Widget 测试、真机测试、多设备兼容性验证
文档与博客系列 15% 50 篇博客、README、项目文档、代码注释
发布与审核 5% AppGallery 上架、证书管理、隐私政策、商店截图

关键观察

  • 环境搭建占据了四分之一的时间——这是鸿蒙 Flutter 开发最大的门槛。DevEco Studio 与 Flutter 工具链的磨合、签名证书的配置、模拟器连接问题,每一项都可能消耗数天。如果你的团队考虑鸿蒙 Flutter,建议为环境搭建预留充足的缓冲时间。
  • 文档投入 15% 看起来奢侈,但物超所值。写博客的过程迫使我系统性地审视每一个技术决策,多次在写作中发现代码中隐藏的边界条件问题。这也是后续 AppGallery 审核中隐私政策一次通过的底气所在。
  • 程序化资源生成虽然只占 15%,但避免了长期维护负担。不需要维护二进制资源文件的版本控制、不需要追踪版权来源、不需要在每次设计变更时重新导出 PNG/WAV。

四、技术亮点(展开)

4.1 BreathingCircle:动画驱动与状态机设计

BreathingCircle 是整个应用最核心的交互组件,负责引导用户完成 4-7-8 呼吸法。其技术实现包含三个层次的协同:

  • AnimationController:驱动圆形缩放动画,配合 CurvedAnimation 实现缓入缓出的自然呼吸节奏。呼吸周期通过 repeat(reverse: true) 实现无限循环,每个周期精确映射到一个呼吸阶段(吸气/屏息/呼气)。
  • Timer 层:独立于动画系统的计时器负责管理阶段切换。每完成一个呼吸阶段,Timer 触发状态转换——这个设计确保了即使动画帧率波动,阶段时长依然精确。
  • 状态机BreatheState 枚举定义了 idleinhaleholdexhalepaused 五种状态。暂停/恢复逻辑通过保存动画当前进度值实现无缝恢复,而不是简单地 stop/start。

难点:在鸿蒙平板上测试时发现,部分设备的 AnimationController 在应用切换到后台后不会自动暂停,导致恢复时动画跳帧。解决方案是在 didChangeAppLifecycleState 中显式调用 AnimationController 的停止与重定向。

4.2 MoodChart:纯 Widget 柱状图

没有引入 fl_chartsyncfusion,完全用 Flutter 原生 Widget 实现了一个情绪趋势柱状图:

  • 每个柱子是一个 AnimatedContainer,高度通过情绪评分(1-5)映射为 20%-100% 的容器高度。
  • 五级颜色映射:深绿(愉悦)→ 浅绿(平静)→ 黄(中性)→ 橙(低落)→ 红(沮丧),使用 HSV 色彩空间均匀插值,确保色觉障碍用户可辨识(亮度差异化)。
  • 横轴通过 Row + Expanded 实现自适应分布,不依赖绝对定位。
  • 图例和标签使用 Column + Text 组合,完全响应式。

为什么不用第三方库:鸿蒙 Flutter 的第三方图表库兼容性参差不齐。fl_chart 在鸿蒙上渲染异常(Canvas 坐标偏移),syncfusion 需要商业授权。自己实现虽然多了 150 行代码,但零依赖、零兼容性问题、零授权费用。

4.3 WAV 编码器:60 行手写

纯 Dart 实现 16-bit PCM mono WAV 文件生成。核心逻辑:

[RIFF 头 4B] + [文件大小 4B] + [WAVE 标记 4B] +
[fmt 块 24B:PCM=1, mono=1, sampleRate, byteRate, blockAlign, bitsPerSample=16] +
[data 块 8B + 音频采样数据]

使用 dart:typed_dataByteData 进行小端字节序写入。采样数据通过 Int16List 直接写入,避免了逐字节转换的性能开销。生成的 WAV 文件在 Windows、Android、鸿蒙系统播放器上均验证通过。

4.4 PNG 编码器:100 行手写 + 花瓣纹理算法

完整的 PNG 编码管线:

  1. 花瓣纹理生成:使用极坐标玫瑰曲线 r = cos(k * theta)(k = 花瓣数),对每个像素计算是否落在花瓣形状内。花瓣之间使用径向渐变过渡(白色到蓝色),中心叠加淡黄色花蕊。
  2. zlib 压缩:利用 Dart SDK 内置的 dart:io 中的 ZLibEncoder(无需额外依赖),对滤波后的像素数据进行 Deflate 压缩。
  3. CRC32 校验:手写了 PNG 规范要求的 CRC32 算法,用于 IHDR、IDAT、IEND 三个 chunk 的完整性校验。
  4. PNG 块组装:IHDR(图像元数据)→ IDAT(压缩像素数据)→ IEND(文件结束标记),严格按照 PNG 规范顺序写入。

为什么不用 dart:ui toImage + toByteData:这些 API 需要一个 Flutter 渲染上下文(即 Widget 树),无法在纯 Dart 脚本中运行。手写 PNG 编码器使得 generate_cover.dart 可以在 CI/CD 流水线中以纯命令行模式运行,不依赖 Flutter 引擎。

4.5 高斯噪声合成:Box-Muller + 滤波 + 调制

四种自然音效的生成链路:

  1. 白噪声基:Box-Muller 算法从均匀随机数生成高斯分布噪声,模拟自然界中的随机底噪。
  2. 滤波塑形:雨声 → 低通滤波(模拟雨滴的低频闷响);溪流 → 带通滤波(保留水流的潺潺频率);篝火 → 高频衰减(模拟火焰的噼啪闷响);风声 → 低频振荡调制(模拟风的忽大忽小)。
  3. 包络调制:对滤波后的信号应用 ADSR 包络,模拟自然声音的起落特征(如风声的渐强渐弱)。
  4. 归一化与量化:最终输出归一化到 16-bit PCM 范围(-32768 ~ 32767),写入 WAV 文件。

局限性:纯算法合成的声音"干净"但缺少真实录音的复杂泛音结构。白噪音作为放松背景音是可以接受的,但如果追求高保真自然音效,建议接入真实录音库。


五、遇到的坑

# 问题 根因 解决方案
1 Hive 崩溃 FFI 找不到原生库 迁移到 hive_ce
2 某鸿蒙平板 Hive.initFlutter 失败 应用沙箱路径差异 降级到 systemTemp
3 签名验证失败 bundleName 不一致 统一为 com.flutter.brufen
4 模拟器 DevEco 连接超时 虚拟化冲突 关闭 Hyper-V
5 音频插件全部不可用 鸿蒙无原生音频 API 视觉脉冲替代,规划后期接入

六、测试覆盖与质量指标

项目采用了分层测试策略,覆盖了数据层、业务逻辑层和 UI 层:

测试层级 覆盖范围 用例数 策略
单元测试 MoodModel、AppSettings、WAV 编码器、PNG 编码器、噪声合成算法 18 纯 Dart,无 Flutter 依赖,CI 中毫秒级完成
Widget 测试 MoodPicker、MoodChart、BreathingCircle、MoodTimeline 8 使用 pumpWidget + MaterialApp 包裹,验证渲染与交互
手动真机测试 4 个主页面在鸿蒙手机 + 平板上的完整流程 12 个场景 DevEco Studio 连接真机,覆盖安装/卸载/权限/后台恢复

未覆盖的部分

  • 集成测试(端到端自动化):鸿蒙目前缺乏稳定的 Flutter 集成测试驱动(flutter drive 对鸿蒙支持有限)。
  • 性能测试:未使用 DevEco Profiler 做系统级性能分析。
  • 无障碍测试:未覆盖 TalkBack/ScreenReader 的语义标注。

质量反馈循环:在开发过程中,所有单元测试和 Widget 测试在每次提交前通过 flutter test 运行,平均耗时 3 秒。这使得重构时可以快速验证是否引入回归——在将 Hive 迁移到 Hive CE 的过程中,测试套件捕获了 2 处 API 调用不兼容的问题,避免了手动测试的时间成本。


七、经验教训:给开发者的六条 actionable 建议

  1. "纯 Dart"是跨平台的第一优先级筛选条件。在选择任何第三方包之前,先检查它是否包含原生代码(Android/iOS/HarmonyOS 的 .kt/.swift/.ets 文件)。纯 Dart 包可以在所有 Flutter 支持的平台上无缝运行——对鸿蒙开发者来说,这省去了无尽的编译链调试。
  2. 先跑通"上架流水线",再写功能代码。建议在项目第二周就尝试完成一次 AppGallery 的空壳上传——签名证书、bundleName、隐私政策、应用截图,这些看似"发布阶段"的事情,如果留到最后两周,会变成阻塞项。我在签名证书上浪费了整整三天,因为 bundleName 在 module.json5build-profile.json5 中不一致。
  3. 不要过早引入状态管理框架ChangeNotifier + ListenableBuilder 足够支撑 15 个页面以下的 Flutter 应用。Provider/Bloc/Riverpod 是好的工具,但它们带来的模板代码和心智模型切换成本,在小项目中是净负收益。你可以在确实需要的时候再迁移——Flutter 的 Widget 树重构成本远低于后端服务。
  4. 程序化生成资源不仅省空间,更是可复现性的保障。如果你的应用图标、音频文件是通过脚本生成的,那么任何人都可以 dart run generate_cover.dart 重现完全一致的产物。这在开源协作和 CI/CD 中有巨大的工程价值,也避免了"源文件丢了"这种经典事故。
  5. 写博客是最高效的代码审查方式。在写 50 篇系列文章的过程中,我在解释每一个技术点的时候至少有 5 次发现代码中的潜在问题——边界条件遗漏、错误处理不完整、命名不规范。因为你要向读者"解释"你的代码,你就不得不用更挑剔的眼光审视它。
  6. 鸿蒙生态仍在快速演进,保持"插件备用方案"意识。对于依赖原生平台 API 的功能(音频播放、相机、通知),至少要准备一个降级方案——纯视觉替代、模拟数据、功能开关。这能确保你的应用在插件不可用时依然是可运行、可演示、可上架的。

八、如果重来一次——我会做什么不同

8.1 架构层面

  • Hive CE 的 TypeAdapter 应该更早写,而不是等到数据模型稳定后。项目早期手动做了很多 JSON 序列化/反序列化,迁移到 TypeAdapter 后扔掉了约 80 行样板代码。如果从一开始就用 @HiveType 注解标记 Model 类,可以节省大量重构时间。
  • 导航设计应该考虑"底部导航 + 嵌套路由"。当前使用的是简单的 IndexedStack + 页面切换,当未来需要从"呼吸页"跳转到"情绪详情页"时,会面临路由状态管理难题。GoRouter 或 Navigator 2.0 的早期引入会更好。

8.2 工程实践

  • 应该建立 CI/CD 流水线而不是手动构建。每次 DevEco Studio 构建耗时约 3 分钟,手动构建了至少 30 次——累计浪费了两个小时。GitHub Actions 或 AtomGit CI 配置大约只需要半天,往后的每一次提交都能自动验证。
  • Widget 测试应该和 UI 组件同步编写,而不是事后补。项目中期有三次重构(MoodPicker 布局调整、BreathingCircle 参数化、MoodChart 颜色映射变更),每次重构后都需要手动验证 UI 是否正常。如果当时有 Widget 测试,每次重构后 flutter test 3 秒就能给出答案。

8.3 产品设计

  • 应该在早期就做一次用户访谈。我的"4-7-8 呼吸法"和"五种情绪分级"设计来自文献调研,但从未在真实用户中验证过。如果能在第一版原型阶段就拿给 3-5 个人试用,可能会发现"情绪粒度不够"或"呼吸节奏太难跟随"等问题,避免后期返工。
  • 考虑添加一个引导页(Onboarding)。当前应用打开即是主界面,首次使用的用户可能不清楚"情绪记录"和"白噪音"的关系、不知道呼吸引导怎么用。一个 3 页的滑动引导页可以显著降低新用户的流失率。

九、用户反馈与社区反响

9.1 当前状态

项目于 AppGallery 上架后,截至复盘时,尚处于早期分发阶段。因为是个人项目,未进行付费推广,主要依靠开源社区和博客系列的有机流量。

9.2 已获得的初步反馈

  • 博客系列反响:50 篇系列文章在 AtomGit/CSDN 合计获得约 3000 阅读量,其中"环境搭建"和"签名证书"类文章的阅读量最高,说明鸿蒙 Flutter 开发者的首要痛点是开发环境配置。
  • 开源社区:GitCode 仓库获得约 20 个 Star,有 2 位开发者提了 Issue 询问鸿蒙 Flutter 的编译问题。

9.3 计划中的用户调研

  • 应用内反馈:计划在 2.0 版本中添加"设置 -> 反馈"入口,收集真实的用户评价。
  • 目标用户画像验证:设想中目标用户是 18-35 岁、有轻度情绪管理需求的城市人群,但这一假设尚未通过数据验证。
  • A/B 测试:如果有足够的用户基数(DAU > 100),计划对"纯视觉白噪音 vs. 真实音频白噪音"的效果做一组 A/B 对照。

9.4 对后来者的建议

如果你也在做一个个人全栈应用并希望获得早期反馈,我的建议是:在功能开发的同时,先完成博客/社交媒体渠道的建设。一篇好的技术文章可能带来 10 倍于商店搜索的初始用户,而且技术读者往往是最有价值的种子用户——他们能给出有深度的反馈。


十、系列文章索引

篇章 篇号 核心内容
第一篇 01-10 环境搭建、Hive CE、Stage 模型、离线设计、编译构建、图标生成
第二篇 11-20 情绪模型、MoodPicker、时间线、柱状图、呼吸模式、呼吸球、白噪音、触觉反馈
第三篇 21-30 ChangeNotifier、CRUD、AppSettings、初始化流水线、Tab 架构、错误处理
第四篇 31-42 AnimatedBuilder、隐式动画、渐变、脉冲、WAV、噪声、PNG、zlib、零资源策略
第五篇 43-50 单元测试、Widget 测试、AppGallery 发布、证书管理、Git Workflow、项目复盘

十一、展望

  1. 音频播放接入:等待鸿蒙音频插件成熟,启用已生成的 WAV 文件
  2. 数据导出:支持导出情绪数据为 CSV/JSON
  3. 多设备类型:适配 tablet 和 2in1 设备
  4. 深色模式:Material 3 的 dark ColorScheme
  5. 国际化:英文版本

十二、给后来者的结语

如果你正在考虑启动一个 Flutter + 鸿蒙的个人项目,以下是我在写完 50 篇文章、完成一个完整应用后最想说的三句话:

第一,鸿蒙 Flutter 的坑比想象中少,但比想象中深。 基本 UI 和业务逻辑几乎零摩擦——Flutter 的跨平台能力在鸿蒙上兑现得很好。真正卡人的地方是三个:签名证书配置、原生插件兼容性、模拟器连接。这三个问题各烧掉了我至少一天的时间。好消息是,一旦跨过这些坎,后续的开发体验和 Android/iOS 几乎没有差别。

第二,做好一个"小"产品比做完一个"大"产品难。 这个项目没有用户系统、没有云同步、没有社交功能——看起来很简单。但真正把 4 个页面打磨到"可以用",需要的精力远超预期。动画的缓动曲线调了 3 版、情绪颜色的对比度改了 5 次、WAV 编码器重写了 2 遍。如果你也追求"小而美",请做好心理准备:小不等于快。

第三,50 篇文章写完后,最大的收获不是项目本身,而是写作过程中建立的系统性思维。 当你强迫自己把每一个技术决策写成 2000 字的中文文章时,那些模糊的"我觉得这样比较好"会变成清晰的"因为 A、B、C 三个原因,在 X 约束下,Y 方案优于 Z 方案"。这种思维方式的转变,是任何教程都教不了的。


项目源码https://gitcode.com/PengXiansheng/E-Brufen
全系列索引README.md


作者简介:E-Brufen Dev,Flutter & 鸿蒙开发者。希望这 50 篇文章对你的鸿蒙 Flutter 之旅有所帮助。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐