开头直接进入主题,聊聊在 OpenHarmony 上跑 Flutter 这件事。说实话,Flutter for OpenHarmony 从出现到真正可用,中间经历过一段“看起来很美、用起来想哭”的阶段,但最近大半年,工具链和插件生态已经扎实了不少。这篇实战系列的第一期,我会以“每日热点 App”为具体落地场景,完整走一遍项目初始化、鸿蒙插件配置、工程结构设计、编译联调的全流程,把其中踩过的坑和绕过的弯都摊开来讲。
如果你是刚接触 OpenHarmony 的 Flutter 开发者,或者已经在做鸿蒙原生开发、想用 Flutter 做跨端统一,这篇文章应该是能直接抄作业的。项目初始化是最容易出幺蛾子的环节,很多问题都出在“环境对了但配置不对”或者“插件路径没配对”,我会把每一步的命令、参数、配置文件内容都贴出来,并解释为什么这么配。
1. 内容整体设计与思路拆解
1.1 项目背景:为什么是“每日热点”这个 App
在 OpenHarmony 生态里做 App,最缺的其实是“能跑、能看、能扩展”的示例工程。官方文档和 Demo 偏向单点能力展示,比如一个列表、一个组件、一个 canvas 绘画,但真实的业务 App 涉及网络请求、状态管理、多页面路由、平台通道调用等组合动作。
“每日热点”这个题材选得比较讨巧:它天然需要一个信息流页面、一个详情页面,还要处理网络数据解析、下拉刷新、加载状态,这些组合在一起能覆盖 Flutter 日常开发 80% 的高频场景。而且热点数据源可以直接用公开 API 或者本地 Mock 数据,不用纠结后端服务,项目初始化阶段就能把大部分技术链路跑通,对后续扩展也友好。
1.2 技术选型:为什么选用 Flutter 而非 ArkUI 单独开发
在 OpenHarmony 上开发应用,原生选择自然是 ArkUI,但如果你手里已经有一个 Flutter 版本的应用,或者在 Android、iOS 上已经用 Flutter 积累了组件库和业务逻辑,直接用 Flutter for OpenHarmony 可以把这些资产复用过来。
这里需要补一个认知:Flutter for OpenHarmony 不是简单地把 Flutter Engine 交叉编译到 OpenHarmony 上,而是由 OpenHarmony 团队维护了一个独立的适配分支,提供 flutter_flutter 的社区版本,同时通过 ohos 平台目录完成针对 OpenHarmony 的构建产物生成。这意味着你可以用一套 Dart 代码,同一套 Flutter 组件树,同时构建出 Android、iOS 和 OpenHarmony(HAP/APP)三个平台的应用。
实践下来,这个方案最大的好处是业务代码的复用率极高。比如我自己维护的一个资讯类项目,Android 端和鸿蒙端的 UI 逻辑基本零改动,只有平台通道那部分需要针对 OpenHarmony 的特性做适配。而 ArkUI 学习成本虽然不算高,但如果是成熟团队,从 Flutter 切过去反而浪费了已有的代码资产。
1.3 整体架构规划:项目初始化阶段需要想清楚的事
我习惯在写第一行代码前先把目录结构和依赖关系画清楚,避免后面越写越乱。每日热点 App 的项目初始化阶段,至少要确定这几件事:
- 使用什么样的状态管理:个人推荐
Riverpod或者Provider,前者更灵活,后者更简单,看团队熟悉度; - 网络层用哪套:
dio基本是事实标准,拦截器、取消请求、日志打印都方便; - 路由方案:直接用
Navigator2.0 或者go_router,考虑到后面要加 Web 端,go_router会更合适; - 鸿蒙插件需要哪些:第一版先跑通系统能力(比如剪贴板、传感器),后续再看业务需要接入哪些 ohos 插件。
这些决策不复杂,但需要在项目初始化时落实到位。因为 Flutter for OpenHarmony 的工程结构和标准 Flutter 工程有个重要差异——它会多出一个 ohos 目录,这个目录对应着 OpenHarmony 的工程配置,包括 module.json5、build-profile.json5 这些鸿蒙特有的配置文件,后续集成插件、配置权限、声明 ability 都要在这里操作。
2. 核心细节解析与实操要点
2.1 Flutter for OpenHarmony 开发环境的完整准备清单
环境准备是项目初始化的第一道坎。官方文档写得比较分散,我根据实际安装过程整理了一份自检清单:
| 依赖项 | 版本要求(以我使用的稳定版为例) | 说明 |
|---|---|---|
| OpenHarmony SDK | API 9 及以上 | 建议直接装 API 10/11,后续插件兼容性更好 |
| DevEco Studio | 4.0 以上 | 用于打开 ohos 工程、签名、打包 HAP |
| Flutter SDK(OpenHarmony 版) | 3.7.x 以上 | 必须使用 OpenHarmony 分支,不能用官方原版 |
| Node.js | 16.0 以上 | 部分工具链依赖 |
| hpm(鸿蒙包管理器) | 最新版 | 通过 npm 安装,用于安装 ohos 依赖 |
| ohpm | DevEco 自带 | 鸿蒙生态的包管理工具,类似 pub |
这里有个关键点容易被忽略:如果你本机已经装了官方 Flutter SDK,需要区分 flutter 命令指向的是哪套 SDK。我当时就是吃了这个亏,flutter doctor 一直显示正常,但构建 OpenHarmony 工程时却提示找不到 ohos 平台,最后发现是环境变量 PATH 里把官方 Flutter 排在了前面。
2.2 OpenHarmony 专用 Flutter SDK 的配置原理
Flutter for OpenHarmony 的 SDK 本质上是一个 fork 分支,其中新增了 engine 对 OpenHarmony 的适配层,以及 flutter_tools 中对 ohos 平台构建命令的支持。官方的 OpenHarmony 分支 SDK 可以从 Gitee 或特定镜像仓库拉取,也可以通过社区维护的部署脚本一键安装。
安装完成后,核心是确认三个环境变量:
FLUTTER_ROOT:指向你的 OpenHarmony Flutter SDK 根目录;DART_SDK:通常位于 SDK 目录下的bin/cache/dart-sdk;PATH:把$FLUTTER_ROOT/bin放到最前面。
配置完成后,在终端执行 flutter doctor,如果输出中能看到类似 OpenHarmony 的选项并且状态为正常,说明 SDK 基本可用。建议再跑一个 flutter config --enable-ohos 之类的命令(不同版本命令可能略有差异),确保 ohos 平台被显式启用,项目初始化时才能通过 flutter create --platforms=ohos 生成对应目录。
2.3 工具链验证:项目初始化前必须做的 3 项检查
正式创建工程之前,我强烈建议先做一次工具链“体检”,避免进入项目后才发现问题,排查起来特别费时间。
第一项检查是 flutter doctor,确认 Flutter SDK 状态和依赖工具是否正常。第二项是 ohpm -v 与 hpm -v,确认鸿蒙包管理工具可用,因为后续项目里很多 ohos 原生依赖要靠它们拉取。第三项是确认 DevEco Studio 能正常打开一个空白 ohos 工程,并成功签名构建,这一步主要是验证调试证书和签名配置没问题。
如果这三项都通过,项目初始化的成功率会非常高。为什么这么说?因为 OpenHarmony 的签名机制比较特殊,不像 Android 调试模式直接用 debug keystore,鸿蒙要求每个应用都配置对应的签名证书,如果签名配置不到位,即使编译通过,安装到设备或模拟器时也会报 install signature verify failed。所以在初始化阶段就顺手把签名链路跑通,后面省很多事。
3. 实操过程与核心环节实现
3.1 使用 flutter create 创建每日热点 App 工程
环境就绪后,开始创建工程。在终端中进入目标目录,执行:
bash复制flutter create --platforms=ohos,android,ios --org com.example.hotnews daily_hot
注意 --platforms 参数里必须显式包含 ohos,否则生成出来的是标准 Flutter 目录结构,没有 ohos 目录。项目名建议用下划线命名,daily_hot 这种格式是 Dart 包名的合法格式。
执行完成后,查看工程目录:
text复制daily_hot/
├── android/
├── ios/
├── ohos/
├── lib/
├── pubspec.yaml
├── ...
ohos 目录就是 OpenHarmony 工程的核心,里面的结构类似 DevEco 创建的 Stage 模型工程,包含:
entry/src/main/module.json5:应用模块配置,包名在这里设;entry/src/main/ets/:OpenHarmony 侧的逻辑代码目录;build-profile.json5:签名与构建配置。
第一次看到这个目录,很多人会奇怪“不是用 Flutter 吗,为什么还有 ets 代码”?其实这是正常的。Flutter 引擎需要有一个 OpenHarmony 原生工程的壳来承载,MainAbility 和 EntryAbility 这些 ets 文件负责启动 Flutter 渲染容器,所以这个目录不能删,后期需要调整 UI 的完整显示模式、处理平台能力时都要动它。
3.2 每日热点 App 的页面结构与数据流设计
项目初始化完成后,我先把 lib 目录按照功能拆好,方便后续扩展:
text复制lib/
├── main.dart
├── app.dart
├── core/
│ ├── network/
│ ├── theme/
│ └── utils/
├── features/
│ ├── home/
│ ├── detail/
│ └── favorites/
└── shared/
└── widgets/
每日热点 App 的第一版规划是三个 Tab:热点列表、分类页面、我的收藏。首页负责展示热点内容流,支持下拉刷新和加载更多;分类页面按类型筛选热点;收藏页用来存放用户标记的内容,后续还可以接入本地数据库实现持久化。
在数据流设计上,首页会通过 dio 请求热点数据源,使用 dart:convert 解析 JSON,再用 Riverpod 的 FutureProvider 管理加载状态。项目初始化阶段,我会先写一个 Mock 数据源,返回写死的热点列表,保证页面能先跑起来,后续再替换为真实 API。
之所以先在工程里搭好数据流骨架,是为了确认从“数据加载”到“UI 渲染”这条链路在 OpenHarmony 上正常工作。如果一上来就写真实接口,出了问题不好定位是网络请求的问题还是 Flutter 渲染的问题,先用 Mock 数据把基础链路验证通过,是最稳妥的做法。
3.3 在 pubspec.yaml 中配置鸿蒙插件与基础依赖
Daily Hot 项目初始化阶段,我在 pubspec.yaml 中添加了以下几类依赖:
yaml复制dependencies:
flutter:
sdk: flutter
cupertino_icons: ^1.0.6
dio: ^5.4.0
flutter_riverpod: ^2.4.0
go_router: ^13.0.0
intl: ^0.18.0
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^3.0.0
这些依赖是跨平台通用的,Android、iOS、OpenHarmony 都能用。关键在于添加依赖后,执行 flutter pub get 时,需要确认 OpenHarmony 侧的插件是否也能正确解析。如果某个插件不支持 ohos 平台,flutter pub get 阶段可能不会报错,但在构建 HAP 时会提示缺少对应的 ohos 实现。
这里要特别提醒:很多 Flutter 插件(比如 shared_preferences、path_provider)需要对应的 ohos 原生实现才能跑通,如果直接使用官方插件最新版,可能会因为缺少 ohos 适配而失败。解决办法是找到社区维护的 shared_preferences_ohos、path_provider_ohos 这类带 ohos 后缀的插件,并在 pubspec.yaml 中通过 dependency_overrides 或者直接依赖 git 仓库指定版本。
Daily Hot 第一版还不需要这些原生能力,所以暂不引入,后续在“收藏”功能落地时会用到本地存储,到时候再针对 ohos 做专门配置。
3.4 ohos 目录的鸿蒙插件与权限配置
在 OpenHarmony 工程中,权限声明是在 module.json5 里配置的。如果后续需要访问网络接口,必须在 requestPermissions 中添加网络权限:
json复制{
"module": {
"name": "entry",
"type": "entry",
"requestPermissions": [
{
"name": "ohos.permission.INTERNET"
}
]
}
}
这一步很容易遗漏。在 Android 上,Flutter 工程默认会在 AndroidManifest.xml 里加上 INTERNET 权限(debug 模式才会),但 OpenHarmony 的 module.json5 不会自动注入,所以首版跑网络请求时经常遇到“Dart 层报请求异常,但实际是原生权限没开”的问题。
另外,如果在实机上调试,还需要在 DevEco Studio 中为应用配置签名。打开 ohos 目录下的 build-profile.json5,在 signingConfigs 里配置好自动签名。automaticallyGenerateSignature 设置为 true 会让 DevEco 自动处理签名流程,适合开发阶段。
3.5 验证 OpenHarmony 插件配置是否生效的判定方法
依赖配置完成并执行 flutter pub get 后,如何判断插件配置真的生效了?我在实践中最常用的办法是:检查 .ohos/ 目录下是否生成了对应的插件符号链接,以及 ohos/entry/src/main/ets/ 下是否有插件自动生成的桥接代码。
具体来说,在工程根目录执行:
bash复制flutter build hap --debug
如果构建成功并生成 .hap 文件,说明整个链路基本通了。如果在构建过程中出现找不到插件、无法解析依赖等问题,可以根据报错信息逐步排查,常见的情况我会在后面“问题排查”部分详细展开。
如果你使用的是 DevEco Studio 来构建 ohos 工程,还可以直接在 IDE 中打开 ohos 目录,然后执行 Build > Build Hap(s)/APP(s) > Build Hap(s)。这种方式的好处是能直观看到构建日志,排错更方便。
3.6 编写可运行的主页面代码
在跑通初始化流程后,我在 lib/main.dart 里写了一个极简但能体现 Flutter 跨端效果的页面:
dart复制import 'package:flutter/material.dart';
import 'app.dart';
void main() {
runApp(const DailyHotApp());
}
app.dart 中定义应用的根组件:
dart复制import 'package:flutter/material.dart';
import 'features/home/home_page.dart';
class DailyHotApp extends StatelessWidget {
const DailyHotApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: '每日热点',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
useMaterial3: true,
),
home: const HomePage(),
);
}
}
HomePage 先做一个带 AppBar 的列表页,数据使用 Mock 的 List<HotNews>:
dart复制import 'package:flutter/material.dart';
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('每日热点')),
body: ListView.builder(
itemCount: 10,
itemBuilder: (context, index) {
return ListTile(
leading: CircleAvatar(child: Text('${index + 1}')),
title: Text('热点新闻标题 ${index + 1}'),
subtitle: Text('这是从 Mock 数据源加载的测试内容'),
trailing: const Icon(Icons.chevron_right),
);
},
),
);
}
}
这段代码看起来没啥稀奇的,但它在 OpenHarmony 上能跑起来本身就说明 Flutter 引擎在鸿蒙环境下的渲染、布局、文本绘制链路是通的。项目初始化阶段,我不建议过早引入复杂动画和自定义绘制,先把基础控件跑通,后面排查问题会更容易。
4. 常见问题与排查技巧实录
4.1 flutter create 后没有 ohos 目录的解决方法
这个问题在论坛里被问得最多。原因多半是 Flutter SDK 不是 OpenHarmony 版本,或者 ohos 平台支持未被启用。
排查步骤:
- 执行
flutter --version,确认版本号中是否包含ohos相关标识,或者用flutter config --list检查平台支持列表; - 如果 SDK 是官方原版,更换为 OpenHarmony 分支 SDK;
- 检查环境变量
FLUTTER_ROOT是否指向正确的目录; - 如果 SDK 没问题,尝试执行
flutter config --enable-ohos后重新创建工程。
如果用的是社区脚本安装的 SDK,注意不要混用官方 Flutter 的命令行工具,两个 SDK 的 flutter 命令会互相干扰。
4.2 构建 HAP 时提示“找不到 ohos 插件实现”
一般在 flutter build hap 阶段出现,比如某个 pub 插件声明了 flutter: 插件能力,但 OpenHarmony 侧没有注册对应的 Plugin 实现,构建工具会直接报错。
我的排查思路是:
- 先看报错信息里的插件名,确认是哪个依赖;
- 去 pub.dev 或者 Gitee 搜索是否有对应的 ohos 适配版;
- 如果有,在
pubspec.yaml中用dependency_overrides强制覆盖为适配版。
例如官方 path_provider 不支持 ohos 时,可以这样覆盖:
yaml复制dependency_overrides:
path_provider:
git:
url: https://gitee.com/xxx/path_provider_ohos.git
这种方式能绕过版本冲突,但要注意覆盖版本和主插件版本是否兼容。日常开发中,建议优先选择社区活跃、星星数量多的 ohos 适配插件,避免后期出现无人维护的问题。
4.3 默认签名无效,HAP 安装失败的问题
新创建的 OpenHarmony 工程默认没有签名配置,通过 DevEco Studio 打开 ohos 目录时,IDE 会提示配置签名。如果你直接使用命令行构建 HAP,然后尝试用 hdc install 安装到设备,大概率会报签名校验失败。
解决方案是先用 DevEco Studio 打开工程,在 File > Project Structure > Signing Configs 中勾选 Automatically generate signature,IDE 会自动生成调试证书并写入 build-profile.json5。之后再用命令行构建,安装就不会有签名问题了。
如果设备是 RK3568 这类开发板,还需要确认系统允许安装调试应用,可能需要先在系统设置里打开“允许安装未知来源应用”之类的选项,具体名称因厂商定制 ROM 而异。
4.4 插件自动生成代码失效,需要手动桥接的处理
有时 flutter pub get 执行后,OpenHarmony 原生侧的插件桥接代码没有自动生成,这通常表现为运行应用时调用某个插件方法提示 MissingPluginException。
排查步骤:
- 删除
ohos/entry/src/main/ets/下自动生成的plugins相关目录; - 重新执行
flutter clean && flutter pub get; - 如果仍未生成,打开 DevEco Studio 构建一次 ohos 工程,让 IDE 触发同步;
- 检查
ohos/entry/src/main/ets/中是否有PluginManager相关文件,并确认其中注册了对应的插件类。
这里踩过最深的一个坑是:修改了 pubspec.yaml 里的插件列表后,直接用 DevEco Studio 构建,结果 IDE 没有重新同步 Flutter 插件注册信息,导致运行时始终找不到插件。后来我养成了习惯,任何插件变更都先在命令行跑一次 flutter pub get,再打开 DevEco 做构建。
5. 避坑清单与开发心得
5.1 项目初始化阶段的 5 条避坑清单
结合实测经验,我把最容易踩的坑整理成了一张清单:
flutter create时不要漏掉--platforms=ohos,否则后续手工添加 ohos 目录很麻烦;- 环境变量
PATH中,OpenHarmony Flutter SDK 的路径必须排在官方 Flutter SDK 之前; module.json5里提前加上INTERNET权限,不要等到网络请求失败再排查;- 首次构建 HAP 前,先用 DevEco Studio 配置一次自动签名;
pubspec.yaml中引入插件时,优先确认是否有 ohos 适配版本,不要在编译阶段才后悔。
5.2 OpenHarmony 侧代码的最小改动原则
很多 Flutter 开发者第一次接触 ohos 目录时,忍不住想去改里面的 ets 文件。我的建议是:项目初始化阶段,尽量保持 OpenHarmony 侧代码零改动,把所有业务逻辑都放在 Flutter 端。
原因很简单:OpenHarmony 侧的代码越少,后续升级 Flutter SDK 或适配新版本时冲突越少。只有遇到真正的平台能力调用(比如读取系统剪贴板、获取设备信息、调用传感器),才需要通过 MethodChannel 或插件的方式,在 ohos 侧写相应的 bridge 代码。
5.3 从“能跑”到“好用”的渐进式开发策略
项目初始化跑通后,不要急着把所有功能都堆上来。我建议按“三阶段”推进:
- 第一阶段:基础页面 + Mock 数据,验证 Flutter 渲染链路和页面跳转;
- 第二阶段:接入真实数据源 + 下拉刷新 + 状态管理,验证网络请求和异步处理;
- 第三阶段:本地收藏 + 持久化 + 平台能力调用,此时再考虑引入 ohos 原生插件。
这种渐进式策略的好处是每个阶段的风险都可控,万一出现问题,定位范围比“一次性写完所有功能再调试”要小得多。我在做每日热点 App 时就是这样推进的,第一阶段跑通花了半天,第二阶段因为网络权限问题多花了小半天,第三阶段反而是最顺利的。
5.4 后续系列规划:每日热点 App 还能往哪里扩展
当前这一期完成了项目初始化和鸿蒙插件配置,后续系列可以继续深入的方向包括:
- 接入真实热点 API,完善下拉刷新和分页加载;
- 实现热点详情页,支持 Markdown 渲染和图片加载;
- 引入
shared_preferences_ohos实现收藏功能; - 增加系统通知能力,定时推送热门话题;
- 发布到 OpenHarmony 应用市场,走完整的签名、打包、上架流程。
每个方向都能深挖不少内容,比如通知推送就涉及 OpenHarmony 的 NotificationManager 能力,这正好能展示 Flutter 与鸿蒙原生能力的结合方式。
6. 写在最后:关于这次实操的一点个人体会
在整个项目初始化与鸿蒙插件配置的过程中,我最深的感受是:OpenHarmony 生态的 Flutter 支持已经过了“能不能用”的阶段,现在更关键的是“怎么用才顺手”。工具链虽然还有一些粗糙的地方,但相比一两年前已经稳很多了,只要严格按照环境要求配置,大概率能一次跑通。
如果你正准备上手 Flutter for OpenHarmony,建议不要只停留在看文档,而是真的动手创建一个项目,哪怕就是跑一个默认的计数器页面,也要完成整个构建、签名、安装的闭环。只有把全链路跑通一次,后面加功能、加插件时才有底气。
最后分享一个小技巧:开发阶段尽量保持命令行构建和 DevEco Studio 构建两套流程都熟练掌握。命令行适合快速验证和自动化脚本,DevEco 适合调试布局和检查原生侧问题。两者配合使用,能覆盖绝大多数日常开发场景。希望这篇文章能帮你少走点弯路,下一篇实战系列文章里,我会接着聊如何把每日热点 App 的首页真正做成一个可用的信息流页面,包括真实数据接入和状态管理的最佳实践。
