Flutter三方库适配鸿蒙【step_counter】模拟计步器应用项目完整实战
Flutter三方库适配鸿蒙【step_counter】模拟计步器应用项目完整实战
前言
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
step_counter 是一个健康运动类 Flutter 示例项目。它没有接入真实传感器,而是通过 Future.doWhile 和 Future.delayed 在前台模拟步数增长,并实时更新步数、目标完成度、卡路里估算、距离估算和小时活动柱状图。
计步器类应用通常涉及传感器、后台记录、权限和健康数据平台。这个项目选择从更轻量的前台模拟入手,适合用来练习 状态管理、异步循环、圆形进度条、统计卡片、柱状图比例计算、按钮状态切换和 OpenHarmony 基础 UI 适配。

图示说明:本文围绕 Flutter 工程中的 step_counter 项目展开,重点分析模拟计步逻辑、目标进度、卡路里与距离估算、小时活动图,以及 OpenHarmony 适配中的真实边界。
计步器的核心体验是“运动状态 + 实时进度 + 数据反馈”。即使是模拟数据,也能完整练习健康类 Dashboard 的状态流转和可视化结构。
本文将基于项目真实源码展开,重点包括:
StepCounterApp的应用入口与绿色 Material 3 主题_steps、_goal、_isWalking的状态关系_simulateSteps()如何每 2 秒模拟步数增加_progress如何驱动圆形目标进度_caloriesBurned与_distanceKm的估算方式_buildStatCard()如何复用统计卡片Hourly Activity柱状图如何按比例计算高度_hourlySteps长度与真实小时取值不匹配的边界- OpenHarmony 适配时应该验证的图标、进度、异步刷新和布局
一、项目背景与目标
1.1 项目定位
step_counter 的定位是一个模拟计步器。用户点击 Start Counting 后,应用会每 2 秒模拟增加一批步数;点击 Stop Counting 后,模拟停止;点击 AppBar 右侧刷新按钮后,步数和小时活动数据归零。
从用户流程看,它包含:
- 打开应用,看到默认 0 步。
- 点击
Start Counting开始模拟计步。 - 观察步数、百分比、卡路里和距离变化。
- 点击
Stop Counting暂停模拟。 - 点击刷新按钮重置数据。
- 查看底部小时活动柱状图。
从工程流程看,它包含:
- 使用
_isWalking表示是否正在计步。 - 使用
_steps保存总步数。 - 使用
_goal保存目标步数。 - 使用异步循环定期增加模拟步数。
- 使用 getter 派生进度、卡路里和距离。
- 使用
CircularProgressIndicator展示目标完成率。 - 使用
Row与Container绘制简易柱状图。
1.2 当前功能概览
| 功能 | 当前实现 | 技术点 |
|---|---|---|
| 应用入口 | runApp(const StepCounterApp()) |
Flutter 启动流程 |
| 应用主题 | 绿色 Material 3 | ColorScheme.fromSeed |
| 总步数 | 默认 0 | _steps |
| 目标步数 | 10000 | _goal |
| 计步状态 | Start / Stop | _isWalking |
| 模拟步数 | 每 2 秒增加 5 到 14 步 | Future.doWhile |
| 进度展示 | 圆形进度条 | CircularProgressIndicator |
| 卡路里估算 | 步数乘 0.04 | _caloriesBurned |
| 距离估算 | 步数除以 1300 | _distanceKm |
| 活动图 | 12 个柱状条 | _hourlySteps |
| 重置 | 清空步数和柱状图 | _reset() |
1.3 适合学习的能力
这个项目适合学习:
- 模拟传感器数据流
- 异步循环与 mounted 判断
- 圆形进度可视化
- 派生统计数据
- 健康类 Dashboard 布局
- 简易柱状图比例计算
- 按钮状态和图标切换
- OpenHarmony 前台 UI 适配验证
二、环境准备与工程结构
2.1 技术栈概览
项目只使用 Flutter SDK 自带能力,没有引入传感器插件。
| 类别 | 当前使用 | 说明 |
|---|---|---|
| 开发语言 | Dart | Flutter 应用主语言 |
| UI 框架 | Flutter Material | 页面、按钮、卡片、图标 |
| 状态管理 | StatefulWidget + setState |
页面内状态 |
| 模拟计时 | Future.doWhile + Future.delayed |
每 2 秒更新一次 |
| 进度组件 | CircularProgressIndicator |
目标进度展示 |
| 柱状图 | Row + Container |
小型活动图 |
| 目标适配 | Flutter / OpenHarmony | 基础 UI 和异步刷新验证 |
2.2 pubspec 关键配置
工程配置如下:
environment:
sdk: ^3.9.2
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^1.0.8
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^5.0.0
flutter:
uses-material-design: true
这里需要注意:
- 当前项目没有
pedometer、传感器或健康数据插件。 - Material Icons 依赖
uses-material-design: true。 - 主要验证 Flutter Framework 层能力,不验证真实计步硬件能力。
2.3 主源码结构
核心代码集中在 lib/main.dart:
import 'package:flutter/material.dart';
void main() {
runApp(const StepCounterApp());
}
主要结构如下:
| 结构 | 类型 | 作用 |
|---|---|---|
StepCounterApp |
StatelessWidget |
应用根组件 |
StepCounterHomePage |
StatefulWidget |
计步器首页 |
_StepCounterHomePageState |
State |
管理步数、状态和统计 |
2.4 常用运行命令
完成 Flutter 环境准备后,可以执行:
flutter pub get
flutter analyze
flutter test
flutter run
OpenHarmony 环境运行时,还需要结合本地 Flutter OpenHarmony 发行版、DevEco Studio、设备连接和签名配置。
三、应用入口与主题配置
3.1 main 函数
应用入口如下:
void main() {
runApp(const StepCounterApp());
}
runApp 会把根组件挂载到 Flutter 渲染树。
3.2 StepCounterApp 根组件
根组件代码如下:
class StepCounterApp extends StatelessWidget {
const StepCounterApp({super.key});
Widget build(BuildContext context) {
return MaterialApp(
title: 'Step Counter',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.green),
useMaterial3: true,
),
home: const StepCounterHomePage(title: 'Step Counter'),
);
}
}
它完成了:
- 设置应用标题为
Step Counter。 - 使用绿色作为 Material 3 种子色。
- 设置首页为
StepCounterHomePage。
3.3 绿色主题的意义
绿色通常用于健康、运动和目标达成场景。项目中绿色被用于:
- 运行状态图标。
- 目标进度条。
- Start Counting 按钮。
- Hourly Activity 柱状图。
- 统计卡片图标。
这让页面视觉语义保持一致。
四、页面状态设计
4.1 状态字段
页面状态如下:
class _StepCounterHomePageState extends State<StepCounterHomePage> {
int _steps = 0;
int _goal = 10000;
bool _isWalking = false;
final List<int> _hourlySteps = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
int _currentHour = DateTime.now().hour;
}
字段含义如下:
| 字段 | 类型 | 作用 |
|---|---|---|
_steps |
int |
当前总步数 |
_goal |
int |
目标步数,默认 10000 |
_isWalking |
bool |
是否正在模拟计步 |
_hourlySteps |
List<int> |
小时活动步数桶 |
_currentHour |
int |
当前小时 |
4.2 状态关系
_isWalking 控制是否增加步数;_steps 控制主进度;_hourlySteps 控制底部柱状图;_goal 控制目标完成比例。
这些状态共同驱动页面:
double get _progress => _steps / _goal;
int get _caloriesBurned => (_steps * 0.04).round();
double get _distanceKm => _steps / 1300;
4.3 真实传感器边界
当前项目没有读取系统传感器,也没有申请运动权限。步数来源是模拟逻辑:
final randomSteps = 5 + (DateTime.now().second % 10);
因此它不是一个真实计步器,而是一个用于学习 UI 状态和数据可视化的模拟计步器。
五、模拟计步逻辑
5.1 initState 启动模拟循环
页面初始化时调用 _simulateSteps():
void initState() {
super.initState();
_simulateSteps();
}
这意味着异步循环在页面创建后就开始运行,但只有 _isWalking 为 true 时才会增加步数。
5.2 _simulateSteps 方法
模拟计步代码如下:
void _simulateSteps() {
Future.doWhile(() async {
await Future.delayed(const Duration(seconds: 2));
if (mounted) {
setState(() {
if (_isWalking) {
final randomSteps = 5 + (DateTime.now().second % 10);
_steps += randomSteps;
_hourlySteps[_currentHour] += randomSteps;
}
});
return true;
}
return false;
});
}
流程如下:
- 每次等待 2 秒。
- 判断页面是否仍然 mounted。
- 如果
_isWalking为 true,就生成模拟步数。 - 增加总步数。
- 增加当前小时桶内步数。
- 返回 true 继续循环。
5.3 模拟步数范围
模拟步数计算如下:
final randomSteps = 5 + (DateTime.now().second % 10);
DateTime.now().second % 10 的范围是 0 到 9,因此每次增加:
| 最小值 | 最大值 |
|---|---|
| 5 | 14 |
这不是随机数,而是基于当前秒数的确定性变化。
5.4 mounted 的作用
异步循环里使用:
if (mounted) {
setState(() {
// update state
});
}
这样可以避免页面销毁后继续调用 setState。
六、开始、停止与重置
6.1 Start / Stop 切换
按钮回调为 _toggleWalking():
void _toggleWalking() {
setState(() {
_isWalking = !_isWalking;
_currentHour = DateTime.now().hour;
});
}
它会切换 _isWalking,并更新当前小时。
6.2 按钮 UI
按钮根据 _isWalking 改变图标、文案和颜色:
ElevatedButton.icon(
onPressed: _toggleWalking,
icon: Icon(_isWalking ? Icons.pause : Icons.play_arrow),
label: Text(_isWalking ? 'Stop Counting' : 'Start Counting'),
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.all(16),
backgroundColor: _isWalking ? Colors.red : Colors.green,
),
)
状态对应关系:
| 状态 | 图标 | 文案 | 颜色 |
|---|---|---|---|
| 未计步 | Icons.play_arrow |
Start Counting |
绿色 |
| 正在计步 | Icons.pause |
Stop Counting |
红色 |
6.3 重置逻辑
重置方法如下:
void _reset() {
setState(() {
_steps = 0;
_hourlySteps.fillRange(0, _hourlySteps.length, 0);
});
}
它会清空总步数和小时活动图。
6.4 重置的真实边界
当前 _reset() 不会把 _isWalking 改为 false。如果用户正在计步时点击重置,下一轮模拟循环仍会继续增加步数。
这不一定是错误,但需要明确:当前重置是清空数据,不是停止计步。如果希望 Reset 同时停止,可以写成:
void _reset() {
setState(() {
_isWalking = false;
_steps = 0;
_hourlySteps.fillRange(0, _hourlySteps.length, 0);
});
}
七、目标进度与圆形 UI
7.1 进度计算
目标进度通过 getter 计算:
double get _progress => _steps / _goal;
默认目标是 10000 步,因此:
| 步数 | 进度 |
|---|---|
| 1000 | 10% |
| 5000 | 50% |
| 10000 | 100% |
7.2 圆形进度条
圆形进度条代码如下:
CircularProgressIndicator(
value: _progress.clamp(0, 1),
strokeWidth: 12,
backgroundColor: Colors.grey.shade200,
valueColor: AlwaysStoppedAnimation(
_progress >= 1 ? Colors.green : Colors.green.shade300,
),
)
_progress.clamp(0, 1) 可以保证传给进度条的值始终在 0 到 1 之间。
7.3 中心内容
进度条中心显示图标、步数和百分比:
Column(
children: [
Icon(
_isWalking ? Icons.directions_walk : Icons.accessibility_new,
size: 48,
color: _isWalking ? Colors.green : Colors.grey,
),
Text('$_steps'),
Text('${(_progress * 100).toInt()}%'),
],
)
图标会跟随计步状态变化:
- 计步中:行走图标,绿色。
- 未计步:静态人体图标,灰色。
7.4 超过目标后的表现
当步数超过目标时,圆形进度条保持满格,因为 value 被限制到 1。但百分比文本会继续增长,例如 12000 步时显示 120%。
这是当前源码的真实表现。
八、卡路里与距离估算
8.1 卡路里估算
卡路里通过 getter 计算:
int get _caloriesBurned => (_steps * 0.04).round();
这表示每步约 0.04 卡路里,是一个非常粗略的估算。
示例:
| 步数 | 卡路里估算 |
|---|---|
| 1000 | 40 |
| 5000 | 200 |
| 10000 | 400 |
8.2 距离估算
距离通过 getter 计算:
double get _distanceKm => _steps / 1300;
这表示约 1300 步为 1 公里。
示例:
| 步数 | 距离估算 |
|---|---|
| 1300 | 1.00 km |
| 6500 | 5.00 km |
| 10000 | 7.69 km |
8.3 估算边界
卡路里和距离都不是精准健康数据,真实数值会受身高、体重、步幅、速度、地形等因素影响。当前实现更适合演示派生数据,而不是医学或训练级统计。
8.4 统计卡片复用
三个统计项使用 _buildStatCard 构建:
_buildStatCard(Icons.local_fire_department, _caloriesBurned.toString(), 'Calories')
_buildStatCard(Icons.straighten, _distanceKm.toStringAsFixed(2), 'km')
_buildStatCard(Icons.flag, _goal.toString(), 'Goal')
这让页面结构更简洁,避免重复写三段相似 UI。
九、统计卡片组件
9.1 _buildStatCard 方法
组件方法如下:
Widget _buildStatCard(IconData icon, String value, String label) {
return Card(
child: Container(
padding: const EdgeInsets.all(12),
child: Column(
children: [
Icon(icon, color: Colors.green),
const SizedBox(height: 4),
Text(
value,
style: const TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
Text(
label,
style: TextStyle(
fontSize: 12,
color: Colors.grey.shade600,
),
),
],
),
),
);
}
9.2 组件参数
| 参数 | 类型 | 作用 |
|---|---|---|
icon |
IconData |
卡片图标 |
value |
String |
主要数值 |
label |
String |
指标名称 |
9.3 组件复用价值
这个方法让统计卡片保持统一样式:
- 图标统一绿色。
- 数值统一 20 号粗体。
- 标签统一 12 号灰色。
- padding 和布局一致。
如果后续增加更多指标,只需要继续调用 _buildStatCard()。
十、Hourly Activity 柱状图
10.1 数据来源
小时活动数据保存在:
final List<int> _hourlySteps = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
当前长度是 12。
10.2 柱状图生成
柱状图使用 List.generate(12, ...) 生成:
children: List.generate(12, (index) {
final maxSteps = _hourlySteps.reduce((a, b) => a > b ? a : b);
final height = maxSteps > 0
? (_hourlySteps[index] / maxSteps) * 80
: 0.0;
return Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Container(
width: 20,
height: height,
decoration: BoxDecoration(
color: index == _currentHour
? Colors.green
: Colors.green.shade200,
borderRadius: BorderRadius.circular(4),
),
),
const SizedBox(height: 4),
Text('$index'),
],
);
})
10.3 高度计算逻辑
先找出最大步数:
final maxSteps = _hourlySteps.reduce((a, b) => a > b ? a : b);
再按最大值计算当前柱高:
final height = maxSteps > 0
? (_hourlySteps[index] / maxSteps) * 80
: 0.0;
最高柱为 80 像素,其余柱按比例缩放。
10.4 当前小时索引的真实问题
_currentHour 来自:
int _currentHour = DateTime.now().hour;
DateTime.now().hour 的范围是 0 到 23。但 _hourlySteps 只有 12 个元素。如果当前时间是 12 点到 23 点,执行下面这行时就可能索引越界:
_hourlySteps[_currentHour] += randomSteps;
这是当前源码中最重要的真实边界。更稳妥的方案是让 _hourlySteps 长度为 24,或者把小时映射到 12 小时桶。
十一、小时图修正方案
11.1 使用 24 小时桶
最直接的修正是把列表改成 24 个元素:
final List<int> _hourlySteps = List.filled(24, 0);
柱状图也生成 24 个:
children: List.generate(24, (index) {
// build bar
})
这样 _currentHour 的 0 到 23 范围就能安全对应列表索引。
11.2 使用 12 小时映射
如果希望保留 12 个柱子,可以映射:
final bucket = DateTime.now().hour % 12;
_hourlySteps[bucket] += randomSteps;
这样不会越界,但上午 9 点和晚上 21 点都会落到同一个桶。
11.3 两种方案对比
| 方案 | 优点 | 边界 |
|---|---|---|
| 24 小时桶 | 数据语义最清晰 | 柱子更多,小屏幕更挤 |
| 12 小时映射 | UI 更紧凑 | 上午和下午会合并 |
11.4 推荐方向
如果目标是健康数据统计,建议使用 24 小时桶,因为它更贴近“今天每小时活动量”的真实含义。小屏幕上可以通过横向滚动或更细柱子解决布局问题。
十二、OpenHarmony 适配要点
12.1 适配关注范围
当前项目没有真实传感器插件,因此适配重点集中在 Flutter 前台 UI 和异步刷新。
| 适配项 | 涉及源码 | 验证重点 |
|---|---|---|
| MaterialApp | 根组件 | 应用启动和主题 |
| AppBar | 刷新按钮 | 图标和点击 |
| CircularProgressIndicator | 圆形进度 | 进度和颜色 |
| Stack | 中心叠加 | 图标、数字、百分比 |
| ElevatedButton | Start / Stop | 状态切换 |
| Card | 统计卡片和活动图 | 间距、阴影 |
| Future.doWhile | 模拟步数 | 定时刷新 |
| Row 柱状图 | Hourly Activity | 小屏布局 |
| Material Icons | 多个图标 | 字体资源 |
12.2 图标资源验证
项目使用了多个 Material Icons:
Icons.refresh
Icons.directions_walk
Icons.accessibility_new
Icons.local_fire_department
Icons.straighten
Icons.flag
Icons.pause
Icons.play_arrow
OpenHarmony 设备上需要确认:
- 图标是否可见。
- 图标颜色是否正常。
- 图标和文本是否对齐。
- Material Icons 字体是否随应用打包。
12.3 异步刷新验证
模拟步数依赖:
await Future.delayed(const Duration(seconds: 2));
适配时需要观察:
- 点击 Start 后步数是否每 2 秒变化。
- 点击 Stop 后步数是否停止增长。
- 点击 Reset 后步数是否清零。
- 页面退出后是否停止 setState。
- 长时间运行是否稳定。
12.4 布局验证
页面包含三个统计卡片和 12 个柱状条。小屏幕需要重点看:
- 三个统计卡片是否挤压。
- Hourly Activity 柱子是否溢出。
- Start Counting 文案是否超出按钮。
- 进度圆环和统计卡片之间间距是否合理。
十三、测试与验证
13.1 静态分析
建议先执行:
flutter analyze
重点关注:
_hourlySteps[_currentHour]是否可能越界。- 异步循环和
mounted判断。 - reset 是否符合预期。
- 统计数据是否只是估算。
13.2 组件测试方向
可以执行:
flutter test
适合覆盖的行为包括:
- 初始显示 0 步。
- 初始按钮为
Start Counting。 - 点击后按钮变为
Stop Counting。 - 点击刷新后步数归零。
- 目标显示为 10000。
- 统计卡片显示 Calories、km、Goal。
13.3 示例测试代码
下面是一段测试按钮切换的思路:
testWidgets('toggles counting state', (tester) async {
await tester.pumpWidget(const StepCounterApp());
expect(find.text('Start Counting'), findsOneWidget);
await tester.tap(find.text('Start Counting'));
await tester.pumpAndSettle();
expect(find.text('Stop Counting'), findsOneWidget);
});
这段测试验证 _isWalking 与按钮 UI 的绑定关系。
13.4 模拟步数测试思路
可以通过等待时间验证模拟步数增长:
testWidgets('simulated steps increase while counting', (tester) async {
await tester.pumpWidget(const StepCounterApp());
await tester.tap(find.text('Start Counting'));
await tester.pump(const Duration(seconds: 3));
expect(find.text('0'), findsNothing);
});
如果当前小时大于 11,这个测试会暴露 _hourlySteps 索引问题,因此修正小时桶后再做稳定测试更合适。
13.5 手动验证流程
手动验证可以按如下顺序进行:
- 启动应用,确认步数为 0。
- 点击
Start Counting,确认按钮变为Stop Counting。 - 等待 2 到 4 秒,确认步数增加。
- 观察卡路里、距离、百分比是否同步更新。
- 点击
Stop Counting,确认步数停止增长。 - 点击刷新按钮,确认步数和活动图清零。
- 观察 Hourly Activity 柱状图是否按比例变化。
- 在 12 点之后运行,重点验证小时索引修正情况。
十四、常见问题与优化建议
14.1 为什么它不是实时传感器计步器
因为当前源码没有接入传感器插件,步数来自模拟逻辑:
final randomSteps = 5 + (DateTime.now().second % 10);
所以它更像一个计步器 UI 和状态流演示项目。
14.2 为什么下午运行可能出错
因为 _currentHour 可能是 12 到 23,而 _hourlySteps 只有 12 个元素:
final List<int> _hourlySteps = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
访问 _hourlySteps[_currentHour] 时可能越界。推荐改为 24 小时桶。
14.3 为什么 Reset 后还会继续增加步数
因为 _reset() 只清空了数据,没有停止 _isWalking:
void _reset() {
setState(() {
_steps = 0;
_hourlySteps.fillRange(0, _hourlySteps.length, 0);
});
}
如果重置时仍处于计步状态,下一次模拟循环会继续加步数。
14.4 卡路里和距离是否准确
当前卡路里和距离是固定公式估算:
int get _caloriesBurned => (_steps * 0.04).round();
double get _distanceKm => _steps / 1300;
它们适合演示,不适合作为精准健康数据。
14.5 是否需要持久化
当前所有数据都在内存中,应用重启后清零。真实运动类应用通常需要保存:
- 每日步数。
- 每小时步数。
- 历史目标完成情况。
- 运动记录时间。
- 用户个性化目标。
十五、工程扩展方向
15.1 接入真实计步传感器
真实计步需要接入平台传感器或健康数据能力。大致流程包括:
- 申请运动传感器权限。
- 监听步数变化。
- 处理应用前后台状态。
- 按天保存基准步数。
- 计算当天真实步数。
OpenHarmony 上还需要结合平台能力确认传感器 API 和权限模型。
15.2 24 小时活动图
推荐把小时桶改成:
final List<int> _hourlySteps = List.filled(24, 0);
生成柱状图时:
children: List.generate(24, (index) {
// build bar
})
这样数据语义更准确。
15.3 增加目标设置
当前目标固定为 10000。可以加入目标设置:
void _updateGoal(int goal) {
setState(() {
_goal = goal;
});
}
再通过步进器或滑块调整目标。
15.4 增加历史记录
可以设计每日记录模型:
class DailyStepRecord {
const DailyStepRecord({
required this.date,
required this.steps,
});
final DateTime date;
final int steps;
}
有了模型后,就可以做日、周、月统计。
15.5 增加真实进度图
当前柱状图是手写 Container。如果后续数据变复杂,可以接入图表库,或者自定义 CustomPainter 绘制更精细的图表。
总结
step_counter 用前台模拟的方式实现了一个计步器界面:它通过 _isWalking 控制是否模拟计步,通过 _steps 保存总步数,通过 _goal 计算目标进度,通过 _caloriesBurned 和 _distanceKm 派生统计数据,通过 CircularProgressIndicator 展示目标进度,并使用 Row、Card 和 Container 绘制统计卡片与小时活动柱状图。
从 OpenHarmony 适配角度看,这个项目覆盖了 Material 主题、AppBar、图标字体、圆形进度条、按钮状态切换、异步前台刷新、统计卡片和简易柱状图等基础能力,适合用来验证 Flutter 健康运动类 Dashboard 在 OpenHarmony 上的表现。
当前源码也有几个真实边界:步数来自模拟逻辑,不是传感器;_hourlySteps 只有 12 个元素,但 _currentHour 可能是 0 到 23,存在索引越界风险;Reset 不会停止计步状态;卡路里和距离只是固定公式估算;数据没有持久化。这些边界不影响它作为入门实战项目使用,但在工程化扩展时需要优先处理。
如果这篇文章对你有帮助,欢迎点赞、收藏、关注,你的支持是我持续创作的动力!
相关资源:
- OpenHarmony 官网:https://www.openharmony.cn
- OpenHarmony 文档:https://docs.openharmony.cn
- 开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
- Flutter 官网:https://flutter.dev
更多推荐

所有评论(0)