尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Flutter 应用迁移 HarmonyOS NEXT 实战:食谱 App 适配指南

Flutter 应用迁移 HarmonyOS NEXT 实战:食谱 App 适配指南 简介这份源码资源面向希望入门鸿蒙原生开发或探索跨平台迁移方案的开发者围绕HarmonyOS NEXT与Flutter的融合实践给出一个可运行的食谱App完整工程。项目共36个文件压缩包约113KB以json5与json配置、ets事件脚本、ts逻辑代码为主辅以png界面素材、gitignore与txt说明文档覆盖依赖声明、构建配置、页面逻辑与资源管理各环节。目录中AppScope、entry、hvigor等模块划分清晰便于理解鸿蒙工程结构与Flutter集成方式。目前已有307人学习下载。读者可借此掌握HarmonyOS NEXT开发环境搭建、Flutter跨平台UI构建与响应式布局要点并参考json5配置的灵活扩展与TypeScript静态检查带来的可维护性提升为后续多端应用开发积累可复用的工程模板与排错思路。1. 从 Android 到 HarmonyOS NEXTFlutter 迁移食谱 App 到底在迁什么2024 年起HarmonyOS NEXT 彻底移除了 AOSP 兼容层这意味着原本跑在 Android 上的 Flutter 应用不能再直接安装运行。很多团队手里有一套成熟的 Flutter 食谱类 App——菜谱列表、食材搜索、收藏、购物清单——现在需要把它迁到 HarmonyOS NEXT 上。这个标题讲的不是从零写一个 App而是如何把已有的 Flutter 工程适配到鸿蒙生态同时保留 Flutter 的跨平台开发效率。适合谁看手里有 Flutter 项目、需要上架鸿蒙应用市场的移动端开发者或者正在评估「Flutter 能不能跑在 HarmonyOS NEXT 上」的技术负责人。核心问题有三个Flutter 引擎在鸿蒙上怎么跑、平台通道怎么替换、源码工程怎么组织。接下来按实际迁移路径拆开讲每一步都落到可复现的操作上。2. 迁移前的技术选型Flutter 在 HarmonyOS NEXT 上的三种跑法2.1 三种方案的能力边界与适用场景目前把 Flutter 应用搬到 HarmonyOS NEXT 上常见做法有三条路选错了后面全是返工。方案一Flutter 鸿蒙适配版社区维护的 flutter_flutter 分支。这是主流做法基于 Flutter 官方 SDK 做鸿蒙平台适配把 Dart 运行时和 Skia 渲染引擎编译到鸿蒙的 ArkTS 运行时之上。优点是不用改 Dart 层业务代码缺点是需要用特定的 Flutter SDK 版本且部分插件需要鸿蒙化替换。方案二混合开发Flutter 页面嵌入 ArkTS 原生壳。用 ArkTS 写主框架和原生能力如分布式数据、卡片服务Flutter 只负责内容展示页。适合需要深度使用鸿蒙特性的 App但通信成本高。方案三完全重写为 ArkTS。放弃 Flutter用 ArkUI 声明式语法重写。开发效率下降明显但如果 App 本身不复杂、且要深度接入鸿蒙原子化服务可以考虑。对于食谱类 App我一般推荐方案一。食谱 App 的核心是列表渲染、图片加载、本地数据库、搜索过滤这些 Flutter 侧已经很成熟没必要重写。只有涉及鸿蒙特有的卡片、流转、分布式能力时才通过平台通道调用原生。2.2 环境搭建Flutter 鸿蒙 SDK 的安装与验证选好方案后第一步是把环境跑通。这里不写具体版本号因为适配版迭代很快以你拿到的 SDK 包内 README 为准。# 1. 下载 Flutter 鸿蒙适配版 SDK从社区仓库获取压缩包 # 解压到本地目录例如 ~/flutter_harmony # 2. 配置环境变量 export PUB_HOSTED_URLhttps://pub.flutter-io.cn export FLUTTER_STORAGE_BASE_URLhttps://storage.flutter-io.cn export PATH$PATH:$HOME/flutter_harmony/bin # 3. 验证 Flutter 环境 flutter doctor -v # 4. 检查是否识别到 HarmonyOS 工具链 # 输出中应出现 HarmonyOS toolchain 相关条目 flutter doctor逻辑说明PUB_HOSTED_URL和FLUTTER_STORAGE_BASE_URL指向国内镜像避免拉依赖时超时。flutter doctor是环境自检命令重点看两项——Flutter 版本是否为鸿蒙适配分支、HarmonyOS SDK 路径是否被正确识别。如果 doctor 输出里没有鸿蒙工具链说明 SDK 路径或 DevEco Studio 配置有问题先解决这个再往下走。参数说明-v是 verbose 模式输出详细诊断信息排查环境问题时必加。日常开发用不带-v的版本即可。2.3 创建鸿蒙平台目录flutter create 的鸿蒙参数环境通了之后给现有 Flutter 工程补上鸿蒙平台目录。# 在已有 Flutter 项目根目录执行 flutter create --platformsohos . # 如果是从零建项目 flutter create --platformsohos --org com.example recipe_app逻辑说明--platformsohos告诉 Flutter 为鸿蒙平台生成宿主工程会在项目下创建ohos/目录里面是 ArkTS 壳工程和构建配置。.表示在当前目录就地补全不会覆盖已有 Dart 代码。参数说明--org是包名反写影响鸿蒙应用的 bundleName上架前必须改成自己的域名反写否则应用市场审核不过。执行完后检查ohos/目录结构重点看entry/src/main/ets/下的入口 Ability 和build-profile.json5里的 SDK 配置。这两处是后续调试和打包的核心文件。3. 食谱 App 核心功能的鸿蒙化改造从插件替换到平台通道3.1 插件兼容性排查哪些包能直接用哪些必须换Flutter 生态的插件分三类纯 Dart 包、含原生代码的插件、含平台通道的插件。纯 Dart 包如provider、dio不用改直接能用。含 Android/iOS 原生代码的插件如sqflite、shared_preferences、image_picker需要找鸿蒙替代品或自己写鸿蒙实现。食谱 App 常见依赖的替换思路原插件用途鸿蒙方案sqflite本地数据库用鸿蒙 relationalStore 封装平台通道或换纯 Dart 的 driftshared_preferences键值存储用鸿蒙 preferences 封装或换 hiveimage_picker选图调鸿蒙 photoAccessHelperpath_provider路径获取用鸿蒙 context.filesDir 封装url_launcher打开链接调鸿蒙 want 机制排查方法在pubspec.yaml里逐个检查依赖凡是带android/或ios/目录的包都要确认是否有鸿蒙适配版。没有的话要么找社区替代要么自己写平台通道。3.2 平台通道改造MethodChannel 换成鸿蒙的写法Flutter 侧调用原生能力靠 MethodChannel鸿蒙侧需要在 ArkTS 里注册对应的通道处理器。以获取设备文件路径为例。Flutter 侧代码保持不变import package:flutter/services.dart; class PlatformPath { static const _channel MethodChannel(com.example.recipe/path); // 获取应用文件目录鸿蒙侧返回 filesDir static FutureString getFilesDir() async { final result await _channel.invokeMethodString(getFilesDir); return result ?? ; } }鸿蒙侧在 EntryAbility 的 onWindowStageCreate 里注册// entry/src/main/ets/entryability/EntryAbility.ets import { MethodChannel } from ohos/flutter_ohos; onWindowStageCreate(windowStage: window.WindowStage) { // 注册与 Flutter 侧同名的通道 const channel new MethodChannel( this.context, com.example.recipe/path, StandardMethodCodec.INSTANCE ); channel.setMethodCallHandler({ onMethodCall: (call: MethodCall, result: MethodResult) { if (call.method getFilesDir) { // 返回鸿蒙应用沙箱文件目录 result.success(this.context.filesDir); } else { result.notImplemented(); } } }); }逻辑说明通道名com.example.recipe/path必须两端完全一致大小写敏感。鸿蒙侧用setMethodCallHandler注册回调根据call.method分发。result.success()回传数据result.notImplemented()表示方法未实现Flutter 侧会收到 MissingPluginException。参数说明StandardMethodCodec.INSTANCE是标准编解码器对应 Flutter 默认的编解码方式。如果传二进制数据改用StandardMessageCodec。this.context.filesDir是鸿蒙应用沙箱路径等价于 Android 的getFilesDir()。3.3 本地数据库迁移从 sqflite 到鸿蒙 relationalStore食谱 App 的菜谱数据、收藏记录、购物清单都需要本地持久化。原来用 sqflite 的鸿蒙侧要换成 relationalStore。最省事的做法是保持 Dart 侧接口不变底层换实现。// 定义抽象接口Dart 侧业务代码只依赖这个 abstract class RecipeStore { FutureListRecipe queryAll(); Futurevoid insert(Recipe recipe); Futurevoid delete(int id); } // 鸿蒙实现通过平台通道调 relationalStore class HarmonyRecipeStore implements RecipeStore { static const _channel MethodChannel(com.example.recipe/db); override FutureListRecipe queryAll() async { final list await _channel.invokeMethodList(queryAll); return list?.map((e) Recipe.fromMap(e)).toList() ?? []; } override Futurevoid insert(Recipe recipe) async { await _channel.invokeMethod(insert, recipe.toMap()); } override Futurevoid delete(int id) async { await _channel.invokeMethod(delete, {id: id}); } }逻辑说明用抽象接口隔离存储实现业务层不感知底层是 sqflite 还是鸿蒙 relationalStore。迁移时只换实现类不动页面代码。这是控制迁移成本的关键设计。参数说明invokeMethodList的泛型指定返回类型鸿蒙侧返回的数组会被自动映射为 Dart List。recipe.toMap()把对象转成 Map跨通道传输时用标准编解码器序列化。鸿蒙侧 relationalStore 的建表和查询逻辑写在 ArkTS 里核心是RdbStore的executeSql和querySql。建表语句和原来 sqflite 的 SQL 基本一致注意鸿蒙的字段类型映射INTEGER 对应 numberTEXT 对应 stringREAL 对应 number。4. 避坑与排查迁移过程中最容易翻车的五个地方4.1 现象flutter doctor 识别不到鸿蒙工具链原因DevEco Studio 的 SDK 路径没有配到环境变量或者 Flutter 鸿蒙分支的flutter config里没指定 HarmonyOS SDK 位置。解决先确认 DevEco Studio 安装目录下的sdk文件夹存在然后执行flutter config --ohos-sdk/path/to/harmonyos/sdk。如果还不行检查flutter doctor -v输出里 OHOS 相关的报错行通常是路径拼写或权限问题。4.2 现象应用安装到鸿蒙设备后白屏日志无 Dart 报错原因Flutter 引擎初始化失败常见于ohos/目录下的build-profile.json5里 SDK 版本与设备系统版本不匹配或者 Flutter 引擎的.so库没有正确打包进 HAP。解决检查build-profile.json5的compileSdkVersion和compatibleSdkVersion确保不高于设备系统版本。然后在 DevEco Studio 的 Build 输出里搜索libflutter.so确认它被包含在 HAP 包里。缺失的话检查ohos/entry/libs/目录下是否有对应架构的引擎库。4.3 现象平台通道调用返回 MissingPluginException原因鸿蒙侧通道注册时机太晚Flutter 侧已经发起调用但原生侧还没注册好。或者通道名两端不一致。解决确保通道注册在onWindowStageCreate里、Flutter 页面加载之前完成。通道名建议定义成常量两端引用同一个字符串避免手写出错。如果用的是懒加载页面把注册逻辑提前到 Ability 创建阶段。4.4 现象图片加载慢列表滚动卡顿原因鸿蒙侧的网络图片加载没有走 Flutter 的图片缓存或者用了不兼容的图片解码路径。Flutter 在鸿蒙上默认走 Skia 渲染图片解码如果落到 ArkTS 侧再回传开销很大。解决优先用 Flutter 的Image.network让图片加载留在 Dart 侧。如果必须用鸿蒙原生图片能力确保返回的是文件路径或字节流不要在通道里传 Bitmap 对象。列表项用ListView.builder懒加载配合cacheExtent控制预加载范围。4.5 现象打包 HAP 时提示签名配置错误原因鸿蒙应用上架需要签名调试签名和发布签名是两套。ohos/目录下默认生成的是调试签名直接用来打发布包会报错。解决在 DevEco Studio 的 Project Structure 里配置发布证书和 Profile 文件。签名配置写在build-profile.json5的signingConfigs字段里。调试阶段可以用自动签名上架前必须换成手动配置的发布签名。证书申请流程在鸿蒙开发者后台完成这里不展开。5. 源码工程组织与上架前的验证清单5.1 推荐的目录结构迁移完成后工程目录应该长这样recipe_app/ ├── lib/ # Dart 业务代码迁移时基本不动 │ ├── models/ # 数据模型 │ ├── pages/ # 页面 │ ├── stores/ # 状态管理 │ └── platform/ # 平台通道封装按平台分文件 │ ├── recipe_store.dart │ └── harmony_store.dart ├── ohos/ # 鸿蒙宿主工程 │ ├── entry/ │ │ ├── src/main/ets/ │ │ │ ├── entryability/ │ │ │ └── pages/ │ │ └── libs/ # Flutter 引擎库 │ └── build-profile.json5 ├── pubspec.yaml └── test/ # 单元测试关键原则Dart 业务代码和平台实现分离。lib/platform/下按平台分文件通过条件导入或运行时判断选择实现。这样同一套代码可以同时跑 Android 和鸿蒙维护成本最低。5.2 上架前的功能验证清单打包发布前逐项过一遍检查项验证方法通过标准冷启动时间杀进程后重新打开3 秒内进入首页列表滚动帧率DevEco Studio 性能分析器稳定 55fps 以上数据库读写增删改查各执行 100 次无异常耗时线性平台通道每个通道方法调用一次返回结果正确图片加载弱网环境加载 20 张图无崩溃有占位签名配置打 release 包并安装安装成功能启动权限声明检查 module.json5只声明实际使用的权限5.3 一个容易忽略的细节字体和深色模式鸿蒙系统默认字体和 Android 不同Flutter 在鸿蒙上如果没指定字体可能回退到系统默认导致中文显示异常。解决办法是在pubspec.yaml里显式声明字体资源或者在 ArkTS 壳工程里配置字体映射。深色模式方面鸿蒙的深色模式切换会触发系统级回调Flutter 侧需要监听PlatformDispatcher.instance.onPlatformBrightnessChanged并重建主题。如果没处理用户切深色模式后 App 还是浅色体验割裂。我自己的习惯是迁移完成后先在真机上把冷启动、列表滚动、数据库读写、深色模式切换这四个场景各跑十遍确认没有偶发崩溃再打包。食谱 App 的用户对卡顿和闪退很敏感一次翻车就可能丢一批用户。希望帮到你。本文还有配套的精品资源点击获取
返回列表