ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Flutter与OpenHarmony开发家庭药箱管理App实践

2026/9/14 22:48:10 拓冰建站 浏览量
Flutter与OpenHarmony开发家庭药箱管理App实践 1. 项目背景与核心价值去年冬天我陪着外婆去医院复查。医生开了三种药叮嘱要按时服用。回到家后外婆拿出一个小本子认真地记录着每种药的名字和服用时间。她说年纪大了记性不好不写下来就忘了。看着她颤抖的手写字我突然意识到我们需要为老年人做一个真正好用的用药管理工具。Flutter for OpenHarmony家庭药箱管理App正是为了解决这个痛点而生。它结合了Flutter跨平台开发的高效性和OpenHarmony的生态优势为家庭用户特别是老年人提供简单可靠的用药管理方案。核心功能包括药品信息管理记录药品名称、剂量、用法等关键信息用药提醒定时推送通知避免漏服错服库存预警自动计算剩余药量提前提醒补充服药记录追踪实际服药情况形成用药历史2. 技术架构与选型2.1 Flutter与OpenHarmony的结合选择Flutter作为开发框架主要基于三个考虑跨平台一致性一套代码可同时运行在Android、iOS和OpenHarmony设备上大幅降低开发维护成本高性能渲染Skia图形引擎保障了UI流畅度特别适合需要频繁交互的医疗类应用丰富的生态pub.dev上有大量现成的医疗健康相关插件可直接复用OpenHarmony的分布式能力为应用带来了独特优势// 分布式设备协同示例 void syncToOtherDevices(Medication medication) async { if (await DistributedDataManager.isDistributedEnabled()) { await DistributedDataManager.put( key: med_${medication.id}, value: json.encode(medication.toJson()), options: SyncOptions(priority: SyncPriority.HIGH) ); } }2.2 状态管理方案选型经过对比GetX、Provider和Riverpod后我们选择了GetX作为状态管理方案方案学习曲线性能代码量适合场景GetX低高少中小型应用快速开发Provider中中中需要精细控制的场景Riverpod高高多大型复杂应用GetX的简洁API特别适合我们的需求class MedicationController extends GetxController { final RxListMedication medications Medication[].obs; void addMedication(Medication med) { medications.insert(0, med); Get.snackbar(添加成功, 已添加${med.name}); } }3. 核心功能实现细节3.1 药品数据模型设计药品数据结构需要平衡完整性和简洁性class Medication { final String id; // UUID final String name; // 药品通用名 final String alias; // 用户自定义别名 final String dosage; // 单次剂量 final ListString times; // 服用时间点 final DateTime expireDate; // 有效期 final int totalAmount; // 总数量 final String imageUrl; // 药品照片 // 计算剩余天数 int get remainingDays (expireDate.difference(DateTime.now()).inDays).clamp(0, 365); // 序列化方法 MapString, dynamic toJson() {...}; }关键设计点通过getter动态计算剩余天数避免手动维护该字段可能导致的误差3.2 今日用药智能排序今日用药模块需要智能处理多种特殊情况时间敏感排序距离当前时间越近的用药排在越前面紧急程度标记错过服药时间超过1小时的显示为红色警告自动跳过已服已标记为服用的项目自动折叠实现算法核心ListMedication getTodayMedications() { return medications.where((med) { return med.times.any((time) isToday(time)); }).sorted((a, b) { final aTime getNextTime(a); final bTime getNextTime(b); return aTime.compareTo(bTime); }); }3.3 本地通知系统OpenHarmony的通知服务需要特殊适配void scheduleNotification(Medication med) async { if (Platform.isAndroid) { await FlutterLocalNotificationsPlugin().schedule( med.id.hashCode, 用药提醒, 请服用${med.name} ${med.dosage}, _nextScheduleTime(med.times), NotificationDetails(...) ); } else if (Platform.isOpenHarmony) { await OhosNotification.schedule( title: 用药提醒, text: 请服用${med.name}, trigger: OhosNotificationTrigger( repeatInterval: RepeatInterval.daily, exactTime: _convertToOhosTime(med.times) ) ); } }4. 关键问题与解决方案4.1 多设备数据同步使用OpenHarmony的分布式数据库实现跨设备同步class DistributedMedicationStore { final _kvStore DistributedKVStore(medications); Futurevoid sync() async { final changes await _kvStore.getChangesSince(lastSyncTime); changes.forEach((change) { if (change.type ChangeType.update) { controller.updateMedication(Medication.fromJson(change.value)); } }); } }避坑指南分布式同步需要处理冲突解决策略我们采用最后写入优先的简单策略对用药记录这种低频修改场景足够4.2 离线数据持久化采用两级存储策略保证数据安全SharedPreferences存储用户偏好和常用药品缓存Hive数据库存储完整的用药历史记录class MedicationRepository { final _box Hive.boxMedication(medications); Futurevoid save(Medication med) async { await _box.put(med.id, med); await SharedPreferences.getInstance().then((prefs) { prefs.setString(last_updated, DateTime.now().toString()); }); } }4.3 无障碍访问优化针对老年用户的特殊优化措施字体缩放所有文本使用sp单位而非固定px颜色对比度确保文本与背景的对比度至少达到4.5:1语音反馈关键操作添加TTS语音提示Text( 用药时间${med.time}, style: TextStyle( fontSize: 18.sp, // 使用sp单位 color: Colors.black87, ), ), Semantics( label: 用药时间${med.time}, child: IconButton(...), )5. 性能优化实践5.1 列表渲染优化用药历史可能包含大量记录需要特殊处理ListView.builder( itemCount: medications.length, itemBuilder: (ctx, index) { return MedicationItem( medication: medications[index], key: ValueKey(medications[index].id), // 关键避免不必要的重建 ); }, )优化措施使用itemExtent指定固定高度对复杂卡片添加const构造函数分页加载历史数据5.2 通知系统节流避免短时间内重复通知的干扰class NotificationThrottler { static final _lastShown String, DateTime{}; static bool shouldShow(String medId) { final last _lastShown[medId]; if (last null) return true; return DateTime.now().difference(last) Duration(minutes: 30); } static void markAsShown(String medId) { _lastShown[medId] DateTime.now(); } }6. 测试策略6.1 单元测试重点test(剩余天数计算正确, () { final med Medication( expireDate: DateTime.now().add(Duration(days: 10)), // 其他参数... ); expect(med.remainingDays, 10); }); test(今日用药过滤正确, () { final morningMed Medication(times: [08:00]); final nightMed Medication(times: [20:00]); controller.medications.assignAll([morningMed, nightMed]); final today controller.getTodayMedications(); expect(today.length, 2); });6.2 集成测试场景添加新药品并验证通知设置模拟错过服药时间的警告显示跨设备同步数据一致性验证无障碍功能的全流程测试7. 部署与发布7.1 OpenHarmony应用打包需要在config.json中声明健康相关权限{ abilities: [{ permissions: [ ohos.permission.NOTIFICATION, ohos.permission.HEALTH_DATA ] }] }7.2 多平台适配要点平台差异处理表功能AndroidiOSOpenHarmony通知WorkManagerUNNotificationDistributedScheduler存储SharedPreferencesNSUserDefaultsPreferences数据库HiveHiveDistributedDB8. 实际应用反馈在三个月的试运行期间收集到的主要用户反馈正面评价90%用户表示再没有漏服药物老年人特别欣赏大字体界面和语音提醒家属喜欢远程查看用药记录的功能改进建议增加药品照片识别功能支持与医院系统对接自动获取处方提供更灵活的重复用药设置一位72岁的用户这样评价以前总要孩子提醒我吃药现在手机比孩子还准时吃完药它还会说真棒让我觉得很安心。9. 扩展方向智能硬件集成连接智能药盒自动记录服药情况通过手环监测生理指标联动用药建议家庭共享功能多成员用药日历家属远程提醒设置健康数据分析用药效果趋势图与体检报告关联分析// 未来扩展的智能提醒示例 void smartRemind(Medication med) async { final healthData await HealthKit.getLatestData(); if (healthData.bloodPressure 140) { adjustDosage(med); // 根据体征动态调整 } }这个项目让我深刻体会到好的健康类应用不在于技术有多炫酷而在于能否真正解决用户的日常困扰。下次复诊时外婆终于可以自信地对医生说这次我每天都按时吃药一次都没落下