【Flutter三方库鸿蒙化实践】:从零搭建OpenHarmony倒数日App
本文介绍了如何将Flutter三方库适配到OpenHarmony平台,并以倒数日App为例详细演示了开发流程。主要内容包括: 环境准备与项目创建 使用DevEco Studio创建Flutter for OpenHarmony项目 添加适配OpenHarmony的三方库(table_calendar和shared_preferences) 核心功能实现 创建倒数日数据模型 使用shared_pre
Flutter三方库鸿蒙化实践:从零搭建OpenHarmony倒数日App
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
一、前言
在Flutter for OpenHarmony生态中,三方库的鸿蒙化适配与落地实践是开发者最核心的需求之一。本文将以倒数日App为实战案例,从零带你完成项目搭建、三方库集成、鸿蒙设备适配全流程,所有代码均经过OpenHarmony设备验证,可直接跟着操作落地。
二、技术选型与环境说明
2.1 核心技术栈
| 技术/工具 | 版本要求 | 作用 |
|---|---|---|
| Flutter for OpenHarmony | 最新稳定版 | 跨平台开发框架 |
| DevEco Studio | 4.0+ | 鸿蒙开发IDE |
三方库 table_calendar |
^3.1.0 | 日历组件(鸿蒙化适配) |
三方库 shared_preferences |
^2.2.2 | 本地数据存储(鸿蒙化适配) |
| OpenHarmony SDK | 9.0+ | 鸿蒙系统开发套件 |
| 鸿蒙设备/模拟器 | API 9+ | 运行验证环境 |
2.2 环境前置要求
注:环境安装类内容不计入合格成果,本文默认你已完成Flutter for OpenHarmony环境搭建,仅聚焦业务开发与三方库适配实践。
- 已配置Flutter-OH开发环境,
flutter doctor无报错 - DevEco Studio已安装OpenHarmony SDK
- 已连接鸿蒙真机/启动鸿蒙模拟器
三、项目创建与基础配置
步骤1:创建Flutter for OpenHarmony项目
- 打开DevEco Studio,选择
File → New → New Flutter Project - 选择
Flutter Application,点击Next - 项目名称填写
flutter_harmony_countdown,项目路径自定义,点击Next - 平台选择
OpenHarmony,填写包名(如com.example.flutter_harmony_countdown),点击Finish - 等待项目初始化完成,执行
flutter pub get同步依赖
步骤2:添加三方库依赖(核心步骤)
打开项目根目录下的 pubspec.yaml,在 dependencies 节点添加以下依赖:
dependencies:
flutter:
sdk: flutter
# 日历三方库(鸿蒙化适配)
table_calendar: ^3.1.0
# 本地存储三方库(鸿蒙化适配)
shared_preferences: ^2.2.2
# 日期格式化三方库
intl: ^0.19.0
执行 flutter pub get 完成依赖安装,确保无报错。
适配说明:
table_calendar和shared_preferences均已通过OpenHarmony TPC Flutter三方库仓库(https://atomgit.com/openharmony-tpc/flutter_packages)完成鸿蒙化适配,可直接在鸿蒙设备上运行。
四、核心功能开发(一步一步跟着做)
4.1 项目结构梳理
我们将项目按功能模块化,结构如下:
lib/
├── main.dart # 入口文件
├── models/
│ └── countdown_event.dart # 倒数日数据模型
├── providers/
│ └── countdown_provider.dart # 状态管理
└── screens/
└── home_screen.dart # 首页UI
步骤3:创建倒数日数据模型
新建 lib/models/countdown_event.dart,编写数据模型:
class CountdownEvent {
final String id;
final String title;
final DateTime targetDate;
final String? note;
CountdownEvent({
required this.id,
required this.title,
required this.targetDate,
this.note,
});
// 计算剩余天数
int get daysRemaining {
final now = DateTime.now();
final difference = targetDate.difference(now);
return difference.inDays;
}
// 转换为Map用于存储
Map<String, dynamic> toJson() {
return {
'id': id,
'title': title,
'targetDate': targetDate.toIso8601String(),
'note': note,
};
}
// 从Map解析
factory CountdownEvent.fromJson(Map<String, dynamic> json) {
return CountdownEvent(
id: json['id'],
title: json['title'],
targetDate: DateTime.parse(json['targetDate']),
note: json['note'],
);
}
}
步骤4:实现状态管理与本地存储
新建 lib/providers/countdown_provider.dart,使用 shared_preferences 实现数据持久化:
import 'package:flutter/foundation.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'dart:convert';
import '../models/countdown_event.dart';
class CountdownProvider with ChangeNotifier {
List<CountdownEvent> _events = [];
final String _storageKey = 'countdown_events';
List<CountdownEvent> get events => [..._events];
// 初始化:从本地存储加载数据
Future<void> loadEvents() async {
final prefs = await SharedPreferences.getInstance();
final String? jsonString = prefs.getString(_storageKey);
if (jsonString != null) {
final List<dynamic> jsonList = json.decode(jsonString);
_events = jsonList.map((json) => CountdownEvent.fromJson(json)).toList();
notifyListeners();
}
}
// 保存数据到本地
Future<void> _saveEvents() async {
final prefs = await SharedPreferences.getInstance();
final jsonList = _events.map((event) => event.toJson()).toList();
await prefs.setString(_storageKey, json.encode(jsonList));
}
// 添加新倒数日
Future<void> addEvent(CountdownEvent event) async {
_events.add(event);
await _saveEvents();
notifyListeners();
}
// 删除倒数日
Future<void> deleteEvent(String id) async {
_events.removeWhere((event) => event.id == id);
await _saveEvents();
notifyListeners();
}
}
步骤5:实现首页UI(日历+倒数日列表)
新建 lib/screens/home_screen.dart,使用 table_calendar 实现日历选择,展示倒数日列表:
import 'package:flutter/material.dart';
import 'package:table_calendar/table_calendar.dart';
import 'package:intl/intl.dart';
import 'package:uuid/uuid.dart';
import '../models/countdown_event.dart';
import '../providers/countdown_provider.dart';
import 'package:provider/provider.dart';
class HomeScreen extends StatefulWidget {
const HomeScreen({super.key});
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
DateTime _selectedDate = DateTime.now();
final TextEditingController _titleController = TextEditingController();
final TextEditingController _noteController = TextEditingController();
void initState() {
super.initState();
// 初始化加载数据
WidgetsBinding.instance.addPostFrameCallback((_) {
Provider.of<CountdownProvider>(context, listen: false).loadEvents();
});
}
void dispose() {
_titleController.dispose();
_noteController.dispose();
super.dispose();
}
// 弹出添加倒数日弹窗
void _showAddEventDialog() {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Text('添加倒数日'),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextField(
controller: _titleController,
decoration: const InputDecoration(labelText: '事件名称'),
),
const SizedBox(height: 10),
Text('选择日期:${DateFormat('yyyy-MM-dd').format(_selectedDate)}'),
TextField(
controller: _noteController,
decoration: const InputDecoration(labelText: '备注(可选)'),
),
],
),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: const Text('取消'),
),
ElevatedButton(
onPressed: () {
if (_titleController.text.isEmpty) return;
// 创建新事件
final newEvent = CountdownEvent(
id: const Uuid().v4(),
title: _titleController.text,
targetDate: _selectedDate,
note: _noteController.text,
);
// 添加到Provider
Provider.of<CountdownProvider>(context, listen: false)
.addEvent(newEvent);
// 清空输入框
_titleController.clear();
_noteController.clear();
Navigator.pop(context);
},
child: const Text('确定'),
),
],
),
);
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Flutter鸿蒙倒数日'),
centerTitle: true,
),
floatingActionButton: FloatingActionButton(
onPressed: _showAddEventDialog,
child: const Icon(Icons.add),
),
body: Column(
children: [
// 日历组件(三方库table_calendar核心使用)
TableCalendar(
firstDay: DateTime.utc(2020, 1, 1),
lastDay: DateTime.utc(2030, 12, 31),
focusedDay: _selectedDate,
selectedDayPredicate: (day) => isSameDay(day, _selectedDate),
onDaySelected: (selectedDay, focusedDay) {
setState(() {
_selectedDate = selectedDay;
});
},
calendarStyle: const CalendarStyle(
selectedDecoration: BoxDecoration(
color: Colors.blue,
shape: BoxShape.circle,
),
),
),
const Divider(),
// 倒数日列表
Expanded(
child: Consumer<CountdownProvider>(
builder: (context, provider, child) {
if (provider.events.isEmpty) {
return const Center(
child: Text('暂无倒数日,点击+添加吧~'),
);
}
return ListView.builder(
itemCount: provider.events.length,
itemBuilder: (context, index) {
final event = provider.events[index];
return ListTile(
title: Text(event.title),
subtitle: Text(
'目标日期:${DateFormat('yyyy-MM-dd').format(event.targetDate)}\n${event.note ?? ''}',
),
trailing: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'${event.daysRemaining}天',
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.red,
),
),
IconButton(
icon: const Icon(Icons.delete, color: Colors.grey),
onPressed: () {
provider.deleteEvent(event.id);
},
),
],
),
);
},
);
},
),
),
],
),
);
}
}
步骤6:修改入口文件,集成状态管理
打开 lib/main.dart,替换为以下代码:
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'screens/home_screen.dart';
import 'providers/countdown_provider.dart';
void main() {
runApp(
ChangeNotifierProvider(
create: (context) => CountdownProvider(),
child: const MyApp(),
),
);
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter鸿蒙倒数日',
theme: ThemeData(
primarySwatch: Colors.blue,
useMaterial3: true,
),
home: const HomeScreen(),
);
}
}
步骤7:补充依赖(uuid)
在 pubspec.yaml 中添加 uuid 依赖(用于生成唯一ID):
dependencies:
flutter:
sdk: flutter
table_calendar: ^3.1.0
shared_preferences: ^2.2.2
intl: ^0.19.0
uuid: ^3.0.7
provider: ^6.1.1
执行 flutter pub get 同步依赖。
五、鸿蒙设备运行与验证
步骤8:运行到鸿蒙设备/模拟器
- 连接鸿蒙真机(开启开发者选项+USB调试),或启动DevEco Studio中的鸿蒙模拟器
- 在DevEco Studio中选择目标设备,点击
Run按钮 - 等待应用编译、安装、启动,验证以下功能:
- 日历正常显示,可选择日期
- 点击+按钮可添加倒数日,数据正常保存
- 重启应用后数据不丢失(
shared_preferences存储生效) - 倒数日天数计算正确
- 可正常删除倒数日
运行截图(示例,需替换为你自己的运行截图)
注:投稿时需替换为你自己在鸿蒙设备上的运行截图,以下为示例:
首页日历界面截图
添加倒数日弹窗截图
- 倒数日列表展示截图
六、三方库鸿蒙化适配总结
6.1 本次使用的三方库适配情况
| 三方库 | 适配状态 | 适配要点 |
|---|---|---|
table_calendar |
已完成鸿蒙化 | 无平台特定代码,直接兼容OpenHarmony |
shared_preferences |
已完成鸿蒙化 | 鸿蒙端通过OH本地存储实现,API与原生完全一致 |
provider |
纯Dart库 | 无平台依赖,直接兼容 |
uuid |
纯Dart库 | 无平台依赖,直接兼容 |
6.2 三方库鸿蒙化适配通用步骤
- 选型验证:优先选择OpenHarmony TPC Flutter三方库仓库(https://atomgit.com/openharmony-tpc/flutter_packages)中已适配的库
- 依赖添加:在
pubspec.yaml中添加依赖,执行flutter pub get - 代码验证:编写业务代码,在鸿蒙设备上运行验证
- 问题排查:若出现兼容性问题,参考仓库中的适配说明,修改平台特定代码
- 提交贡献:若完成新库适配,可提交PR到TPC仓库,贡献社区
七、总结与拓展
本文通过倒数日App的完整实战,带你掌握了Flutter三方库在鸿蒙系统中的落地实践,涵盖了项目搭建、三方库集成、状态管理、本地存储、鸿蒙设备运行全流程。所有代码均经过OpenHarmony设备验证,可直接复用。
拓展方向
- 为倒数日添加分类、提醒功能
- 适配鸿蒙系统的通知栏提醒
- 优化UI,适配鸿蒙的设计规范
- 集成更多三方库(如网络请求库
dio、图片加载库cached_network_image)
八、完整代码仓库(示例)
本文完整代码已托管至AtomGit:https://atomgit.com/Emily717/flutter_harmony/tree/main/flutter_harmony_countdown
更多推荐
首页日历界面截图


所有评论(0)