🚀运行效果展示




Flutter框架跨平台鸿蒙开发------水电费缴费提醒APP的开发流程
前言
随着移动互联网的快速发展,跨平台开发已经成为移动应用开发的主流趋势。Flutter作为Google推出的开源UI工具包,以其"一次编写,多处运行"的特性,为开发者提供了高效、统一的开发体验。本文将详细介绍如何使用Flutter框架开发一款水电费缴费提醒APP,并实现跨平台运行,特别是在鸿蒙操作系统上的适配。
APP介绍
水电费缴费提醒APP是一款专为用户提供水电费账单管理、缴费提醒和统计分析的移动应用。该APP具有以下特点:
- 账单管理:支持添加、编辑、删除水费和电费账单
- 缴费提醒:可设置提前提醒天数和提醒时间,避免逾期缴费
- 统计分析:提供水费、电费的使用趋势和缴费记录统计
- 多平台支持:基于Flutter框架,可在Android、iOS、Web和鸿蒙等平台运行
核心功能实现及代码展示
1. 项目架构设计
本项目采用典型的Flutter三层架构设计:
- 数据层:负责数据的存储和管理,使用Flutter Secure Storage进行本地存储
- 服务层:处理业务逻辑,包括账单管理、通知服务等
- UI层:负责用户界面的展示和交互
2. 数据模型设计
首先,我们需要设计水电费账单的数据模型:
dart
/// 水电费账单模型
class UtilityBill {
/// 账单ID
final String id;
/// 账单类型(水费/电费)
final BillType type;
/// 账单金额
final double amount;
/// 缴费截止日期
final DateTime dueDate;
/// 账单月份
final String month;
/// 缴费状态
final PaymentStatus status;
/// 账单描述
final String description;
/// 构造函数
UtilityBill({
required this.id,
required this.type,
required this.amount,
required this.dueDate,
required this.month,
required this.status,
this.description = '',
});
/// 从Map创建UtilityBill实例
factory UtilityBill.fromMap(Map<String, dynamic> map) {
return UtilityBill(
id: map['id'],
type: map['type'] == 'water' ? BillType.water : BillType.electricity,
amount: map['amount'],
dueDate: DateTime.parse(map['dueDate']),
month: map['month'],
status: map['status'] == 'unpaid' ? PaymentStatus.unpaid : PaymentStatus.paid,
description: map['description'] ?? '',
);
}
/// 转换为Map
Map<String, dynamic> toMap() {
return {
'id': id,
'type': type == BillType.water ? 'water' : 'electricity',
'amount': amount,
'dueDate': dueDate.toIso8601String(),
'month': month,
'status': status == PaymentStatus.unpaid ? 'unpaid' : 'paid',
'description': description,
};
}
/// 计算距离截止日期的天数
int get daysUntilDue {
final now = DateTime.now();
final due = DateTime(dueDate.year, dueDate.month, dueDate.day);
final today = DateTime(now.year, now.month, now.day);
return due.difference(today).inDays;
}
/// 判断是否逾期
bool get isOverdue {
return daysUntilDue < 0;
}
}
/// 账单类型枚举
enum BillType {
water, // 水费
electricity, // 电费
}
/// 缴费状态枚举
enum PaymentStatus {
unpaid, // 未缴费
paid, // 已缴费
}
3. 服务层实现
3.1 账单服务
账单服务负责账单的增删改查和统计功能:
dart
/// 水电费账单服务
class UtilityBillService {
/// 存储键
static const String _storageKey = 'utility_bills';
/// 安全存储实例
final FlutterSecureStorage _storage = FlutterSecureStorage();
/// 获取所有账单
Future<List<UtilityBill>> getBills() async {
try {
final billsJson = await _storage.read(key: _storageKey);
if (billsJson == null) {
return [];
}
final List<dynamic> billsList = json.decode(billsJson);
return billsList
.map((bill) => UtilityBill.fromMap(bill))
.toList();
} catch (e) {
print('Error getting bills: $e');
return [];
}
}
/// 获取未缴费账单
Future<List<UtilityBill>> getUnpaidBills() async {
final allBills = await getBills();
return allBills.where((bill) => bill.status == PaymentStatus.unpaid).toList();
}
/// 添加新账单
Future<void> addBill(UtilityBill bill) async {
try {
final bills = await getBills();
bills.add(bill);
await _saveBills(bills);
} catch (e) {
print('Error adding bill: $e');
throw Exception('添加账单失败');
}
}
/// 更新账单
Future<void> updateBill(UtilityBill updatedBill) async {
try {
final bills = await getBills();
final index = bills.indexWhere((bill) => bill.id == updatedBill.id);
if (index != -1) {
bills[index] = updatedBill;
await _saveBills(bills);
}
} catch (e) {
print('Error updating bill: $e');
throw Exception('更新账单失败');
}
}
/// 删除账单
Future<void> deleteBill(String billId) async {
try {
final bills = await getBills();
bills.removeWhere((bill) => bill.id == billId);
await _saveBills(bills);
} catch (e) {
print('Error deleting bill: $e');
throw Exception('删除账单失败');
}
}
/// 标记账单为已缴费
Future<void> markAsPaid(String billId) async {
try {
final bills = await getBills();
final index = bills.indexWhere((bill) => bill.id == billId);
if (index != -1) {
final updatedBill = UtilityBill(
id: bills[index].id,
type: bills[index].type,
amount: bills[index].amount,
dueDate: bills[index].dueDate,
month: bills[index].month,
status: PaymentStatus.paid,
description: bills[index].description,
);
bills[index] = updatedBill;
await _saveBills(bills);
}
} catch (e) {
print('Error marking bill as paid: $e');
throw Exception('标记账单为已缴费失败');
}
}
/// 保存账单列表到存储
Future<void> _saveBills(List<UtilityBill> bills) async {
try {
final billsJson = json.encode(
bills.map((bill) => bill.toMap()).toList(),
);
await _storage.write(key: _storageKey, value: billsJson);
} catch (e) {
print('Error saving bills: $e');
throw Exception('保存账单失败');
}
}
/// 计算总未缴费金额
Future<double> getTotalUnpaidAmount() async {
final unpaidBills = await getUnpaidBills();
double total = 0.0;
for (final bill in unpaidBills) {
total += bill.amount;
}
return total;
}
}
3.2 通知服务
通知服务负责在账单到期前发送提醒:
dart
/// 通知服务
class NotificationService {
/// 单例实例
static final NotificationService _instance = NotificationService._internal();
/// 本地通知插件
final FlutterLocalNotificationsPlugin _flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
/// 安全存储实例
final FlutterSecureStorage _storage = FlutterSecureStorage();
/// 账单服务实例
final UtilityBillService _billService = UtilityBillService();
/// 工厂构造函数
factory NotificationService() {
return _instance;
}
/// 内部构造函数
NotificationService._internal();
/// 初始化通知服务
Future<void> initialize() async {
const AndroidInitializationSettings initializationSettingsAndroid =
AndroidInitializationSettings('@mipmap/ic_launcher');
const DarwinInitializationSettings initializationSettingsIOS =
DarwinInitializationSettings(
requestAlertPermission: true,
requestBadgePermission: true,
requestSoundPermission: true,
);
const InitializationSettings initializationSettings = InitializationSettings(
android: initializationSettingsAndroid,
iOS: initializationSettingsIOS,
);
await _flutterLocalNotificationsPlugin.initialize(initializationSettings);
}
/// 检查并发送通知
Future<void> checkAndSendNotifications() async {
try {
// 检查是否启用通知
final enableReminders = await _storage.read(key: 'enable_reminders');
if (enableReminders != 'true') {
return;
}
// 获取提醒天数
final reminderDaysStr = await _storage.read(key: 'reminder_days');
final reminderDays = int.tryParse(reminderDaysStr ?? '3') ?? 3;
// 获取所有未缴费账单
final unpaidBills = await _billService.getUnpaidBills();
final now = DateTime.now();
for (final bill in unpaidBills) {
final dueDate = DateTime(bill.dueDate.year, bill.dueDate.month, bill.dueDate.day);
final daysUntilDue = dueDate.difference(now).inDays;
// 检查是否需要发送提前提醒
if (daysUntilDue == reminderDays) {
await _sendNotification(
title: '缴费提醒',
body: '${bill.type == BillType.water ? '水费' : '电费'}账单将于$reminderDays天后到期,金额:¥${bill.amount.toStringAsFixed(2)}',
payload: bill.id,
);
}
// 检查是否需要发送逾期提醒
if (daysUntilDue < 0) {
final enableOverdueReminders = await _storage.read(key: 'enable_overdue_reminders');
if (enableOverdueReminders == 'true') {
await _sendNotification(
title: '逾期提醒',
body: '${bill.type == BillType.water ? '水费' : '电费'}账单已逾期${-daysUntilDue}天,金额:¥${bill.amount.toStringAsFixed(2)}',
payload: bill.id,
);
}
}
}
} catch (e) {
print('Error checking and sending notifications: $e');
}
}
/// 发送通知
Future<void> _sendNotification({
required String title,
required String body,
required String payload,
}) async {
try {
const AndroidNotificationDetails androidPlatformChannelSpecifics = AndroidNotificationDetails(
'utility_bill_reminders',
'水电费缴费提醒',
channelDescription: '用于提醒用户水电费缴费',
importance: Importance.max,
priority: Priority.high,
ticker: 'ticker',
);
const DarwinNotificationDetails iOSPlatformChannelSpecifics = DarwinNotificationDetails();
const NotificationDetails platformChannelSpecifics = NotificationDetails(
android: androidPlatformChannelSpecifics,
iOS: iOSPlatformChannelSpecifics,
);
await _flutterLocalNotificationsPlugin.show(
DateTime.now().millisecondsSinceEpoch ~/ 1000,
title,
body,
platformChannelSpecifics,
payload: payload,
);
} catch (e) {
print('Error sending notification: $e');
}
}
}
4. UI层实现
4.1 主页面
主页面展示账单列表,并提供添加、编辑、删除账单的功能:
dart
/// 水电费账单管理页面
class UtilityBillScreen extends StatefulWidget {
/// 构造函数
const UtilityBillScreen({Key? key}) : super(key: key);
@override
_UtilityBillScreenState createState() => _UtilityBillScreenState();
}
class _UtilityBillScreenState extends State<UtilityBillScreen> {
/// 账单服务实例
final UtilityBillService _billService = UtilityBillService();
/// 账单列表
List<UtilityBill> _bills = [];
/// 加载状态
bool _isLoading = true;
/// 选中的标签页
int _selectedTab = 0;
@override
void initState() {
super.initState();
_loadBills();
}
/// 加载账单数据
Future<void> _loadBills() async {
setState(() {
_isLoading = true;
});
try {
final bills = await _billService.getBills();
setState(() {
_bills = bills;
_isLoading = false;
});
} catch (e) {
print('Error loading bills: $e');
setState(() {
_isLoading = false;
});
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('加载账单失败')),
);
}
}
@override
Widget build(BuildContext context) {
final filteredBills = _getFilteredBills();
return Scaffold(
appBar: AppBar(
title: const Text('水电费管理'),
backgroundColor: Colors.blue,
actions: [
IconButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const UtilityBillReminderSettingsScreen()),
);
},
icon: const Icon(Icons.settings),
),
IconButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const UtilityBillStatisticsScreen()),
);
},
icon: const Icon(Icons.bar_chart),
),
],
),
body: _isLoading
? const Center(child: CircularProgressIndicator())
: Column(
children: [
// 标签页
Container(
margin: const EdgeInsets.all(16),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
color: Colors.grey[200],
),
child: Row(
children: [
Expanded(
child: GestureDetector(
onTap: () => setState(() => _selectedTab = 0),
child: Container(
padding: const EdgeInsets.symmetric(vertical: 12),
alignment: Alignment.center,
decoration: BoxDecoration(
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(12),
bottomLeft: Radius.circular(12),
),
color: _selectedTab == 0 ? Colors.blue : Colors.transparent,
),
child: Text(
'全部',
style: TextStyle(
color: _selectedTab == 0 ? Colors.white : Colors.black,
fontWeight: FontWeight.bold,
),
),
),
),
),
Expanded(
child: GestureDetector(
onTap: () => setState(() => _selectedTab = 1),
child: Container(
padding: const EdgeInsets.symmetric(vertical: 12),
alignment: Alignment.center,
decoration: BoxDecoration(
color: _selectedTab == 1 ? Colors.blue : Colors.transparent,
),
child: Text(
'未缴费',
style: TextStyle(
color: _selectedTab == 1 ? Colors.white : Colors.black,
fontWeight: FontWeight.bold,
),
),
),
),
),
Expanded(
child: GestureDetector(
onTap: () => setState(() => _selectedTab = 2),
child: Container(
padding: const EdgeInsets.symmetric(vertical: 12),
alignment: Alignment.center,
decoration: BoxDecoration(
borderRadius: const BorderRadius.only(
topRight: Radius.circular(12),
bottomRight: Radius.circular(12),
),
color: _selectedTab == 2 ? Colors.blue : Colors.transparent,
),
child: Text(
'已缴费',
style: TextStyle(
color: _selectedTab == 2 ? Colors.white : Colors.black,
fontWeight: FontWeight.bold,
),
),
),
),
),
],
),
),
// 账单列表
Expanded(
child: filteredBills.isEmpty
? const Center(
child: Text(
'暂无账单',
style: TextStyle(fontSize: 16, color: Colors.grey),
),
)
: ListView.builder(
itemCount: filteredBills.length,
itemBuilder: (context, index) {
return _buildBillCard(filteredBills[index]);
},
),
),
],
),
floatingActionButton: FloatingActionButton(
onPressed: () async {
final result = await Navigator.push(
context,
MaterialPageRoute(builder: (context) => const AddUtilityBillScreen()),
);
if (result == true) {
_loadBills();
}
},
backgroundColor: Colors.blue,
child: const Icon(Icons.add),
),
);
}
}
4.2 提醒设置页面
提醒设置页面允许用户配置提醒相关的参数:
dart
/// 缴费提醒设置页面
class UtilityBillReminderSettingsScreen extends StatefulWidget {
/// 构造函数
const UtilityBillReminderSettingsScreen({Key? key}) : super(key: key);
@override
_UtilityBillReminderSettingsScreenState createState() => _UtilityBillReminderSettingsScreenState();
}
class _UtilityBillReminderSettingsScreenState extends State<UtilityBillReminderSettingsScreen> {
/// 安全存储实例
final FlutterSecureStorage _storage = FlutterSecureStorage();
/// 是否启用提醒
bool _enableReminders = true;
/// 提前提醒天数
int _reminderDays = 3;
/// 提醒时间
TimeOfDay _reminderTime = TimeOfDay(hour: 9, minute: 0);
/// 是否启用逾期提醒
bool _enableOverdueReminders = true;
/// 是否启用声音提醒
bool _enableSound = true;
/// 是否启用震动提醒
bool _enableVibration = true;
/// 加载状态
bool _isLoading = true;
@override
void initState() {
super.initState();
_loadSettings();
}
/// 加载设置
Future<void> _loadSettings() async {
try {
final enableReminders = await _storage.read(key: 'enable_reminders');
final reminderDays = await _storage.read(key: 'reminder_days');
final reminderTime = await _storage.read(key: 'reminder_time');
final enableOverdueReminders = await _storage.read(key: 'enable_overdue_reminders');
final enableSound = await _storage.read(key: 'enable_sound');
final enableVibration = await _storage.read(key: 'enable_vibration');
setState(() {
_enableReminders = enableReminders != null ? enableReminders == 'true' : true;
_reminderDays = reminderDays != null ? int.parse(reminderDays) : 3;
_reminderTime = reminderTime != null
? TimeOfDay.fromDateTime(DateTime.parse(reminderTime))
: TimeOfDay(hour: 9, minute: 0);
_enableOverdueReminders = enableOverdueReminders != null ? enableOverdueReminders == 'true' : true;
_enableSound = enableSound != null ? enableSound == 'true' : true;
_enableVibration = enableVibration != null ? enableVibration == 'true' : true;
_isLoading = false;
});
} catch (e) {
print('Error loading settings: $e');
setState(() {
_isLoading = false;
});
}
}
/// 保存设置
Future<void> _saveSettings() async {
try {
await _storage.write(key: 'enable_reminders', value: _enableReminders.toString());
await _storage.write(key: 'reminder_days', value: _reminderDays.toString());
await _storage.write(
key: 'reminder_time',
value: DateTime(
DateTime.now().year,
DateTime.now().month,
DateTime.now().day,
_reminderTime.hour,
_reminderTime.minute,
).toIso8601String(),
);
await _storage.write(key: 'enable_overdue_reminders', value: _enableOverdueReminders.toString());
await _storage.write(key: 'enable_sound', value: _enableSound.toString());
await _storage.write(key: 'enable_vibration', value: _enableVibration.toString());
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('设置已保存')),
);
} catch (e) {
print('Error saving settings: $e');
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('保存设置失败')),
);
}
}
@override
Widget build(BuildContext context) {
if (_isLoading) {
return const Scaffold(
body: Center(child: CircularProgressIndicator()),
);
}
return Scaffold(
appBar: AppBar(
title: const Text('提醒设置'),
backgroundColor: Colors.blue,
),
body: Padding(
padding: const EdgeInsets.all(16),
child: ListView(
children: [
// 提醒开关
Card(
margin: const EdgeInsets.only(bottom: 16),
child: Padding(
padding: const EdgeInsets.all(16),
child: SwitchListTile(
title: const Text('启用缴费提醒'),
subtitle: const Text('开启后将在账单到期前发送提醒'),
value: _enableReminders,
onChanged: (value) {
setState(() {
_enableReminders = value;
});
},
activeColor: Colors.blue,
),
),
),
// 提前提醒天数
Card(
margin: const EdgeInsets.only(bottom: 16),
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text('提前提醒天数', style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
const SizedBox(height: 12),
Row(
children: [
IconButton(
onPressed: _reminderDays > 1
? () {
setState(() {
_reminderDays--;
});
}
: null,
icon: const Icon(Icons.remove),
),
Expanded(
child: Center(
child: Text(
'$_reminderDays 天',
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
),
),
IconButton(
onPressed: _reminderDays < 30
? () {
setState(() {
_reminderDays++;
});
}
: null,
icon: const Icon(Icons.add),
),
],
),
],
),
),
),
// 保存按钮
ElevatedButton(
onPressed: _saveSettings,
style: ElevatedButton.styleFrom(
backgroundColor: Colors.blue,
padding: const EdgeInsets.symmetric(vertical: 16),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
),
child: const Text(
'保存设置',
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
),
),
],
),
),
);
}
}
4.3 统计分析页面
统计分析页面展示账单的使用趋势和缴费记录:
dart
/// 缴费记录追踪和统计页面
class UtilityBillStatisticsScreen extends StatefulWidget {
/// 构造函数
const UtilityBillStatisticsScreen({Key? key}) : super(key: key);
@override
_UtilityBillStatisticsScreenState createState() => _UtilityBillStatisticsScreenState();
}
class _UtilityBillStatisticsScreenState extends State<UtilityBillStatisticsScreen> {
/// 账单服务实例
final UtilityBillService _billService = UtilityBillService();
/// 所有账单
List<UtilityBill> _allBills = [];
/// 加载状态
bool _isLoading = true;
/// 选中的时间范围
String _selectedTimeRange = 'month';
@override
void initState() {
super.initState();
_loadBills();
}
/// 加载账单数据
Future<void> _loadBills() async {
setState(() {
_isLoading = true;
});
try {
final bills = await _billService.getBills();
setState(() {
_allBills = bills;
_isLoading = false;
});
} catch (e) {
print('Error loading bills: $e');
setState(() {
_isLoading = false;
});
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('加载账单失败')),
);
}
}
/// 计算统计数据
Map<String, double> _calculateStatistics() {
final filteredBills = _filterBills();
double totalWater = 0;
double totalElectricity = 0;
double totalPaid = 0;
double totalUnpaid = 0;
for (final bill in filteredBills) {
if (bill.type == BillType.water) {
totalWater += bill.amount;
} else {
totalElectricity += bill.amount;
}
if (bill.status == PaymentStatus.paid) {
totalPaid += bill.amount;
} else {
totalUnpaid += bill.amount;
}
}
return {
'totalWater': totalWater,
'totalElectricity': totalElectricity,
'totalPaid': totalPaid,
'totalUnpaid': totalUnpaid,
'total': totalWater + totalElectricity,
};
}
@override
Widget build(BuildContext context) {
if (_isLoading) {
return const Scaffold(
body: Center(child: CircularProgressIndicator()),
);
}
final statistics = _calculateStatistics();
return Scaffold(
appBar: AppBar(
title: const Text('缴费统计'),
backgroundColor: Colors.blue,
),
body: Padding(
padding: const EdgeInsets.all(16),
child: ListView(
children: [
// 时间范围选择
Container(
margin: const EdgeInsets.only(bottom: 16),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
_buildTimeRangeButton('本月', 'month'),
_buildTimeRangeButton('本季度', 'quarter'),
_buildTimeRangeButton('本年', 'year'),
_buildTimeRangeButton('全部', 'all'),
],
),
),
// 统计卡片
GridView.count(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
crossAxisCount: 2,
crossAxisSpacing: 8,
mainAxisSpacing: 8,
children: [
_buildStatCard('水费总计', statistics['totalWater']!, Colors.blue),
_buildStatCard('电费总计', statistics['totalElectricity']!, Colors.yellow),
_buildStatCard('已缴费', statistics['totalPaid']!, Colors.green),
_buildStatCard('未缴费', statistics['totalUnpaid']!, Colors.red),
],
),
// 总费用
Card(
margin: const EdgeInsets.only(top: 16),
child: Padding(
padding: const EdgeInsets.all(16),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text('总费用', style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
Text('¥${statistics['total']!.toStringAsFixed(2)}', style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
],
),
),
),
// 缴费趋势
_buildTrendChart(),
// 缴费记录
_buildPaymentHistory(),
],
),
),
);
}
}
5. 主入口配置
修改main.dart文件,配置应用的启动逻辑和路由:
dart
import 'package:flutter/material.dart';
import 'screens/utility_bill_screen.dart';
import 'screens/add_utility_bill_screen.dart';
import 'screens/edit_utility_bill_screen.dart';
import 'screens/utility_bill_reminder_settings_screen.dart';
import 'screens/utility_bill_statistics_screen.dart';
import 'services/notification_service.dart';
/// 水电费缴费提醒APP主入口
/// 用于启动水电费缴费提醒APP应用
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// 初始化通知服务
final notificationService = NotificationService();
await notificationService.initialize();
await notificationService.scheduleDailyNotificationCheck();
runApp(const UtilityBillApp());
}
/// 水电费缴费提醒APP根组件
class UtilityBillApp extends StatelessWidget {
/// 构造函数
const UtilityBillApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: '水电费缴费提醒',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
appBarTheme: const AppBarTheme(
backgroundColor: Colors.blue,
elevation: 4,
titleTextStyle: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
elevatedButtonTheme: ElevatedButtonThemeData(
style: ElevatedButton.styleFrom(
backgroundColor: Colors.blue,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12.0),
),
),
),
cardTheme: CardTheme(
elevation: 2,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
),
),
),
debugShowCheckedModeBanner: false,
initialRoute: '/',
routes: {
'/': (context) => const UtilityBillScreen(),
'/add_bill': (context) => const AddUtilityBillScreen(),
'/edit_bill': (context) => EditUtilityBillScreen(bill: ModalRoute.of(context)!.settings.arguments as dynamic),
'/reminder_settings': (context) => const UtilityBillReminderSettingsScreen(),
'/statistics': (context) => const UtilityBillStatisticsScreen(),
},
);
}
}
鸿蒙平台适配
Flutter框架对鸿蒙平台的支持是通过Flutter Engine的鸿蒙适配实现的。在开发过程中,我们需要注意以下几点:
- 权限配置:在鸿蒙应用的配置文件中添加必要的权限,如通知权限等
- 资源适配:确保应用图标、启动画面等资源符合鸿蒙平台的规范
- API兼容性:注意使用跨平台兼容的API,避免使用平台特定的功能
构建流程
在鸿蒙平台构建应用的流程如下:
-
确保已安装鸿蒙开发工具和Flutter的鸿蒙插件
-
在项目根目录执行以下命令:
bashflutter build ohos -
构建成功后,会在
build/ohos/hap目录生成鸿蒙应用安装包(.hap文件)
总结
本文详细介绍了使用Flutter框架开发水电费缴费提醒APP的完整流程,包括项目架构设计、数据模型实现、核心功能开发和鸿蒙平台适配。通过Flutter的跨平台特性,我们成功实现了一款可以在多个平台运行的水电费缴费提醒APP,特别是在鸿蒙操作系统上的良好适配。
项目亮点
- 模块化设计:采用清晰的三层架构,代码结构清晰,易于维护
- 用户友好界面:设计了直观、美观的用户界面,提供良好的用户体验
- 功能完善:实现了账单管理、缴费提醒、统计分析等核心功能
- 跨平台兼容:基于Flutter框架,可在Android、iOS、Web和鸿蒙等平台运行
- 数据安全:使用Flutter Secure Storage进行本地数据存储,保障数据安全
未来展望
- 云同步功能:添加云同步功能,实现多设备数据共享
- 在线缴费:集成在线支付功能,支持直接在APP内完成缴费
- 智能预测:基于历史数据,预测未来的水电费使用情况
- 多语言支持:添加多语言支持,扩大应用的适用范围
通过本项目的开发,我们展示了Flutter框架在跨平台开发中的强大能力,特别是在鸿蒙操作系统上的应用。相信随着Flutter和鸿蒙生态的不断发展,跨平台开发将会变得更加高效和便捷。
📚 参考资料
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net