1. 项目概述:Flutter+OpenHarmony家庭药箱管理App实战
作为一名同时接触过Flutter和OpenHarmony的开发者,这次尝试将两者结合开发家庭药箱管理App的经历让我收获颇丰。这个项目核心解决两个问题:一是利用Flutter的跨平台特性快速构建药箱管理功能,二是在OpenHarmony设备上实现可靠的用药提醒服务。特别值得一提的是用药提醒列表的实现,它需要同时考虑Flutter的UI表现力和OpenHarmony的系统级能力。
选择Flutter+OpenHarmony这个技术组合有几个现实考量:首先,Flutter 3.x版本对OpenHarmony的支持已经趋于稳定;其次,家庭健康类应用需要兼顾快速迭代和硬件适配,这正是两者的优势交集。实际开发中,我发现在OpenHarmony上运行Flutter应用与在Android/iOS上有些微妙差异,特别是在系统级功能调用方面,这些细节我会在后续章节详细说明。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术选型与环境搭建
2.1 Flutter for OpenHarmony环境配置
配置开发环境是第一个关键步骤。与标准Flutter环境不同,针对OpenHarmony需要一些特殊处理:
bash复制# 安装Flutter SDK
git clone https://github.com/flutter/flutter.git -b stable
export PATH="$PATH:`pwd`/flutter/bin"
# 添加OpenHarmony支持
flutter pub global activate flutter_ohos
flutter create --platforms ohos my_medicine_box
环境搭建中最容易出问题的是OHOS SDK的路径配置。我建议在local.properties中明确指定:
code复制flutter.ohos.sdk=/your/path/to/ohos/sdk
flutter.ohos.releaseMode=true
注意:OpenHarmony 3.2+版本需要额外配置签名证书,否则无法安装到真机。建议使用DevEco Studio生成测试证书。
2.2 项目架构设计
采用分层架构保证代码可维护性:
code复制lib/
├── models/ # 数据模型
├── services/ # 业务逻辑
├── utils/ # 工具类
├── widgets/ # 自定义组件
└── ohos/ # OpenHarmony特定实现
关键依赖包选择:
flutter_local_notifications: 用于基础提醒功能ohos_bridge: Flutter与OpenHarmony原生能力交互hive: 本地轻量级数据存储intl: 多语言支持
3. 核心功能实现细节
3.1 药品数据建模与管理
药品数据模型的设计直接影响后续功能实现。我采用了扩展性较强的结构:
dart复制class Medicine {
final String id;
String name;
MedicineType type; // 枚举:药丸/液体/贴剂等
String dosage;
TimeOfDay takeTime;
List<Weekday> repeatDays;
String imageUrl;
// ...其他字段
// 重要:转换为OpenHarmony通知需要的格式
Map<String, dynamic> toNotificationPayload() {
return {
'title': '用药提醒:$name',
'text': '请服用 $dosage',
'hour': takeTime.hour,
'minute': takeTime.minute,
'repeat': repeatDays.map((d) => d.index).toList()
};
}
}
数据存储选用Hive而非SQLite,主要考虑:
- 家庭药箱数据量通常不大
- 需要频繁读写操作
- 对复杂查询需求较少
3.2 跨平台用药提醒实现
这是项目的核心技术难点,需要结合Flutter和OpenHarmony各自优势:
Flutter侧实现UI与逻辑控制
dart复制Future<void> scheduleNotification(Medicine medicine) async {
final payload = medicine.toNotificationPayload();
// 通过MethodChannel调用原生代码
try {
await methodChannel.invokeMethod(
'scheduleNotification',
payload,
);
} on PlatformException catch (e) {
// 错误处理
}
}
OpenHarmony原生能力封装
在ohos/src/main/ets/NotificationHelper.ets中:
typescript复制import reminderAgent from '@ohos.reminderAgent';
export function scheduleNotification(payload: any): Promise<void> {
return new Promise((resolve, reject) => {
const reminderRequest: reminderAgent.ReminderRequest = {
reminderType: reminderAgent.ReminderType.REMINDER_TYPE_TIMER,
triggerTimeInSeconds: calculateTriggerTime(payload.hour, payload.minute),
repeatDays: payload.repeat,
title: payload.title,
content: payload.text,
// ...其他参数
};
reminderAgent.publishReminder(reminderRequest, (err, reminderId) => {
if (err) {
reject(err);
} else {
resolve();
}
});
});
}
关键点:OpenHarmony的reminderAgent比Android的AlarmManager更省电,但需要处理鸿蒙特有的生命周期管理
3.3 用药提醒列表UI实现
采用Sliver系列组件实现高性能滚动列表:
dart复制class ReminderListView extends StatelessWidget {
@override
Widget build(BuildContext context) {
return CustomScrollView(
slivers: [
SliverAppBar(
pinned: true,
expandedHeight: 200,
flexibleSpace: FlexibleSpaceBar(
title: Text('用药计划'),
),
),
SliverPadding(
padding: EdgeInsets.all(16),
sliver: SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) => _buildReminderItem(context, index),
childCount: medicines.length,
),
),
),
],
);
}
Widget _buildReminderItem(BuildContext context, int index) {
return Dismissible(
key: Key(medicines[index].id),
background: Container(color: Colors.red),
onDismissed: (direction) => _deleteReminder(index),
child: Card(
child: ListTile(
leading: MedicineIcon(medicines[index].type),
title: Text(medicines[index].name),
subtitle: Text(_buildScheduleText(medicines[index])),
trailing: Switch(
value: medicines[index].isActive,
onChanged: (v) => _toggleReminder(index, v),
),
),
),
);
}
}
4. 平台特定问题与解决方案
4.1 OpenHarmony适配要点
-
生命周期管理:
- OpenHarmony应用在后台时可能被快速冻结
- 解决方案:在
ability.ts中正确配置backgroundMode
-
通知权限:
typescript复制import abilityAccessCtrl from '@ohos.abilityAccessCtrl'; const requestPermissions = async () => { const permissions: Array<string> = [ 'ohos.permission.NOTIFICATION_CONTROLLER' ]; const atManager = abilityAccessCtrl.createAtManager(); try { await atManager.requestPermissionsFromUser( globalThis.abilityContext, permissions ); } catch (err) { console.error(`Failed to request permissions: ${err}`); } }; -
后台服务保活:
- OpenHarmony限制后台进程
- 替代方案:使用reminderAgent + 系统任务管理白名单
4.2 Flutter插件兼容性问题
常见问题及解决方法:
| 问题现象 | 原因 | 解决方案 |
|---|---|---|
| 插件编译失败 | NDK版本不匹配 | 在ohos/build.gradle中指定ndkVersion |
| 方法调用无响应 | 通道名称不一致 | 确保Flutter侧和原生侧MethodChannel名称完全一致 |
| UI渲染异常 | Skia适配问题 | 在main.dart中设置debugRepaintRainbowEnabled: true排查 |
5. 性能优化实践
5.1 列表滚动优化
针对药品列表可能变长的情况,采用以下优化措施:
- 使用
ListView.builder或SliverList实现懒加载 - 对药品图片实现缓存:
dart复制
CachedNetworkImage( imageUrl: medicine.imageUrl, placeholder: (context, url) => CircularProgressIndicator(), errorWidget: (context, url, error) => Icon(Icons.error), ); - 对复杂计算使用Isolate:
dart复制Future<List<Medicine>> loadFilteredMedicines() async { return await compute(_filterMedicines, filterCriteria); }
5.2 通知系统优化
- 批量操作提醒:
typescript复制function batchSchedule(requests: ReminderRequest[]): Promise<void[]> { return Promise.all(requests.map(req => reminderAgent.publishReminder(req) )); } - 使用精确提醒模式:
dart复制void scheduleExactNotification() { if (Platform.isOHOS) { // OpenHarmony精确提醒 _scheduleOHOSExact(); } else { // Android/iOS后备方案 _scheduleFallback(); } }
6. 测试与调试技巧
6.1 跨平台测试策略
-
单元测试:对核心业务逻辑如用药时间计算进行充分测试
dart复制test('should return correct next reminder time', () { final med = Medicine( takeTime: TimeOfDay(hour: 9, minute: 30), repeatDays: [Weekday.monday, Weekday.friday] ); expect(med.nextReminder(), equals(/* 预期值 */)); }); -
集成测试:验证Flutter与OpenHarmony的交互
dart复制testWidgets('should sync with OHOS reminder', (tester) async { await tester.pumpWidget(MyApp()); await tester.tap(find.byIcon(Icons.add)); // ...执行操作 verify(methodChannel.invokeMethod('scheduleNotification', any)); });
6.2 真机调试要点
- 日志收集:
bash复制
hdc shell hilog -w | grep MyMedicineBox - 常见安装问题排查:
- 签名校验失败 → 检查证书指纹是否匹配
- 权限不足 → 确认config.json中声明了所需权限
- UI显示异常 → 检查设备DPI设置
7. 项目扩展方向
在实际使用过程中,我发现几个有价值的扩展点:
-
智能用药冲突检测:
dart复制class MedicineChecker { static List<Conflict> checkConflicts(List<Medicine> medicines) { // 实现药物相互作用检测逻辑 } } -
家庭共享功能:
- 利用OpenHarmony分布式能力同步数据
- 实现跨设备提醒同步
-
用药记录统计:
dart复制class MedicineStats { final Map<DateTime, int> adherenceRate; final Map<Medicine, int> takenCount; // 其他统计指标 } -
语音交互支持:
typescript复制import voiceAssistant from '@ohos.voiceAssistant'; function registerVoiceCommands() { voiceAssistant.registerCommand({ commands: ['吃药时间到了', '记录用药'], callback: (command) => handleVoiceCommand(command) }); }
在实现这些扩展功能时,Flutter的热重载特性可以极大提升UI开发效率,而OpenHarmony的原生能力则能提供更深入的设备集成。这种组合方式让我在保持开发速度的同时,又能充分利用鸿蒙系统的特色功能。
