作为一名长期从事移动应用开发的工程师,我最近使用Flutter框架完成了一款药品服用记录器的开发。这款应用专为需要长期服药的人群设计,帮助他们科学管理药品信息、跟踪用药记录并监控用药依从性。在实际开发过程中,我发现Flutter的跨平台特性与华为HarmonyOS的适配性表现非常出色,这让我决定将整个开发过程整理成教程分享给大家。
这款应用采用了现代化的Material Design 3设计语言,界面直观友好。核心功能包括今日用药管理、药品信息维护、服用记录追踪、智能统计分析和个性化设置等。从技术架构来看,我们使用了响应式设计确保在不同屏幕尺寸上都能提供一致的用户体验,采用StatefulWidget进行本地状态管理,并通过精心设计的数据模型支持复杂的业务逻辑。
提示:在开始开发前,建议先规划好应用的核心数据结构和状态管理方案,这对后续功能扩展至关重要。
我们的应用采用典型的分层架构设计,主要分为以下几个部分:
这种分层设计使得代码结构清晰,各模块职责明确,便于团队协作和维护。特别是在后期添加新功能时,这种架构的优势更加明显。
在技术选型方面,我们主要基于以下考虑:
特别值得一提的是,我们在HarmonyOS设备上的测试表明,Flutter应用在华为设备上运行流畅,性能表现优异。这为应用在华为生态中的推广提供了良好基础。
药品信息是整个应用最核心的数据结构,我们设计了包含丰富字段的Medication类:
dart复制class Medication {
final String id; // 药品唯一标识
final String name; // 药品名称
final String type; // 剂型(片剂、胶囊等)
final String dosage; // 单次剂量
final String unit; // 剂量单位(mg、ml等)
final String frequency; // 服用频率(每日几次)
final List<String> timesPerDay; // 具体服用时间点
final DateTime startDate; // 开始服用日期
final DateTime? endDate; // 结束服用日期(可选)
final String purpose; // 用药目的
final String sideEffects; // 可能的副作用
final String notes; // 备注信息
// 其他字段...
}
这个模型设计考虑了实际用药场景中的各种需求,如剂量管理、用药时间安排、副作用记录等。特别是timesPerDay字段采用List类型,可以灵活支持一天多次服药的情况。
每次服药都需要记录详细信息,为此我们设计了MedicationRecord类:
dart复制class MedicationRecord {
final String id; // 记录ID
final String medicationId; // 关联的药品ID
final DateTime scheduledTime; // 计划服用时间
final DateTime? actualTime; // 实际服用时间
final String dosageTaken; // 实际服用剂量
final RecordStatus status; // 记录状态
final String notes; // 备注
final int rating; // 服药后感受评分
// 其他字段...
}
这个模型记录了每次服药的计划情况和实际执行情况,为后续的依从性分析提供了数据基础。status字段使用枚举类型,清晰定义了各种可能的服药状态。
为了规范数据并提高代码可读性,我们定义了多个枚举类型:
dart复制// 药品分类枚举
enum MedicationCategory {
prescription, // 处方药
otc, // 非处方药
supplement, // 保健品
vitamin, // 维生素
herbal, // 中药
other, // 其他
}
// 记录状态枚举
enum RecordStatus {
pending, // 待服用
taken, // 已服用
missed, // 错过
skipped, // 跳过
delayed, // 延迟
}
这些枚举类型使代码更加清晰,也便于后续维护和扩展。例如,如果需要添加新的药品分类,只需在枚举中添加相应值即可。
今日用药页面是用户最常访问的界面,需要精心设计用户体验。我们实现了以下关键功能:
核心代码结构如下:
dart复制Widget _buildTodayPage() {
return Column(
children: [
_buildTodayHeader(), // 顶部统计卡片
_buildTodaySchedule(), // 用药计划列表
_buildQuickActions(), // 快速操作面板
],
);
}
统计数据的计算逻辑考虑了各种边界情况:
dart复制void _updateStatistics() {
final today = DateTime.now();
final todayRecords = _records.where((r) =>
r.scheduledTime.year == today.year &&
r.scheduledTime.month == today.month &&
r.scheduledTime.day == today.day).toList();
_todayTaken = todayRecords.where((r) => r.status == RecordStatus.taken).length;
_todayMissed = todayRecords.where((r) => r.status == RecordStatus.missed).length;
final totalScheduled = todayRecords.length;
_adherenceRate = totalScheduled > 0 ? (_todayTaken / totalScheduled) * 100 : 0.0;
}
药品管理模块支持完整的CRUD操作,核心是添加药品对话框的实现:
dart复制class _AddMedicationDialog extends StatefulWidget {
@override
Widget build(BuildContext context) {
return AlertDialog(
title: Text('添加药品'),
content: Form(
child: Column(
children: [
TextFormField(
decoration: InputDecoration(labelText: '药品名称'),
validator: (value) => value?.isEmpty ?? true ? '必填' : null,
),
// 其他表单字段...
],
),
),
actions: [
TextButton(onPressed: () => Navigator.pop(context), child: Text('取消')),
ElevatedButton(onPressed: _saveMedication, child: Text('保存')),
],
);
}
}
这个对话框包含了药品的所有关键信息字段,如表单验证、剂量单位选择、服用频率设置等。我们特别设计了直观的UI,使老年用户也能轻松操作。
每次服药都可以记录详细信息,包括实际服用时间、感受评分等:
dart复制class _TakeMedicationDialog extends StatefulWidget {
@override
Widget build(BuildContext context) {
return AlertDialog(
title: Text('确认服用'),
content: Column(
children: [
Text('药品: ${widget.medication.name}'),
// 感受评分控件
Row(
children: List.generate(5, (index) => IconButton(
onPressed: () => setState(() => _rating = index + 1),
icon: Icon(index < _rating ? Icons.star : Icons.star_border),
)),
),
],
),
actions: [
ElevatedButton(
onPressed: () {
final updatedRecord = widget.record.copyWith(
actualTime: DateTime.now(),
status: RecordStatus.taken,
rating: _rating,
);
widget.onConfirm(updatedRecord);
Navigator.pop(context);
},
child: Text('确认服用'),
),
],
);
}
}
这个功能不仅记录了是否服药,还收集了用户的用药感受,为后续的健康管理提供了宝贵数据。
基于收集的服药记录数据,我们实现了多种统计分析功能:
核心计算逻辑如下:
dart复制double _calculateAdherenceRate() {
final last30Days = DateTime.now().subtract(Duration(days: 30));
final recentRecords = _records.where((r) => r.scheduledTime.isAfter(last30Days)).toList();
if (recentRecords.isEmpty) return 0.0;
final takenCount = recentRecords.where((r) => r.status == RecordStatus.taken).length;
return (takenCount / recentRecords.length) * 100;
}
为确保应用在不同设备上都能良好显示,我们实现了响应式布局:
dart复制Widget _buildResponsiveLayout(BuildContext context, Widget child) {
final screenWidth = MediaQuery.of(context).size.width;
final isTablet = screenWidth > 600;
return Container(
constraints: BoxConstraints(maxWidth: isTablet ? 800 : double.infinity),
child: child,
);
}
对于列表展示,我们也根据屏幕尺寸自动调整列数:
dart复制Widget _buildAdaptiveGrid(List<Widget> children) {
return LayoutBuilder(
builder: (context, constraints) {
final crossAxisCount = constraints.maxWidth > 600 ? 3 : 2;
return GridView.count(
crossAxisCount: crossAxisCount,
children: children,
);
},
);
}
在实际开发过程中,我积累了一些宝贵经验,值得与大家分享:
状态管理选择:对于这种中等复杂度的应用,使用StatefulWidget进行本地状态管理已经足够。如果应用规模更大,可以考虑使用Provider或Riverpod等状态管理方案。
性能优化:
测试建议:
HarmonyOS适配:
注意事项:在开发医疗健康类应用时,要特别注意用户隐私保护。所有健康数据都应该加密存储,并明确告知用户数据使用方式。
这个基础版本完成后,还可以考虑以下扩展方向:
每个扩展方向都需要仔细评估用户需求和开发成本,建议采用迭代式开发,逐步添加新功能。