Flutter 三方库 OpenHarmony 鸿蒙适配实战:dialog_alert 纯 Dart 对话框库评估、改动与鸿蒙 PC 真机验证全流程
Flutter 三方库 OpenHarmony 鸿蒙适配实战:dialog_alert 纯 Dart 对话框库评估、改动与鸿蒙 PC 真机验证全流程
基于 Flutter-OH 3.44.9-dev(Dart 3.12.2)在 Windows 10 22H2 上全程实测通过;真机环节在一台**鸿蒙 PC(OpenHarmony 6.1.1,API 24,arm64,2in1 形态)**上验证。文中所有源码分析、改动内容、构建输出、真机效果均为实际环境抓取,可放心对照复现。
前言
OpenHarmony × Flutter 社区资源
- Flutter-OH 主仓库:CPF-Flutter/flutter_flutter —— SDK 与 Engine 的 OpenHarmony 适配版本
- 三方库适配与开发文档:OpenHarmony-Flutter —— 生态库适配清单与开发规范
- 官方示例与开发指南:openharmony-tpc/flutter_samples —— 环境搭建指导、FAQ 与示例工程
环境搭好之后(还没搭的看这篇环境搭建保姆级教程),下一步就是给项目引入三方库。但拿到一个库就动手改代码是大忌——先评估,再动手,能省掉大量无用功。
本文以 dialog_alert(对话框组件库)为例,完整演示从评估 → 改动 → 构建 → 真机验证的全流程,重点讲清楚一个关键判断:这个库到底需不需要写 ArkTS 原生代码? 答案可能出乎你的意料。


一、库评估:拿到三方库的第一步不是改代码,是判断要不要改
1.1 dialog_alert 基本信息
dialog_alert 是一个 Flutter 对话框组件库,提供 showDialogAlert() 统一接口,支持标题、正文、确认/取消按钮及自定义按钮样式,内部通过 Platform.isIOS 自动切换 Material 和 Cupertino 两种视觉风格——整个实现完全基于 Flutter 自带的 Widget(AlertDialog、TextButton 等),不依赖任何系统原生 API。
| 项目 | 内容 |
|---|---|
| 库名 | dialog_alert |
| pub.dev 版本 | 0.0.3 |
| 功能 | 显示对话框弹窗(Material / Cupertino 双风格) |
| 主要 API | showDialogAlert() |
| 维护状态 | 4 年未更新 |
1.2 六步评估法(来自 ohos-flutter-plugin-adaptation-necessity-check 评估流程)
拿到一个 Flutter 库,按下面六步走一遍就能得出结论:
第 1 步:目录结构检查
用 GitHub API 查看仓库根目录文件列表。dialog_alert 的根目录只有这些:
dialog_alert/
├── lib/ ← Dart 源码
├── example/ ← 示例工程
├── test/ ← 单元测试
├── gif/ ← 演示动图
├── CHANGELOG.md
├── LICENSE
├── README.md
└── pubspec.yaml
没有 android/ 目录,没有 ios/ 目录。 这是第一个强信号——这个库从一开始就没有任何原生平台代码。
第 2 步:pubspec.yaml plugin 声明检查
读 pubspec.yaml 的完整内容:
name: dialog_alert
description: A new Flutter package for showing native alert view in ios
and native alert dialog in android.
version: 0.0.3
homepage: https://github.com/mkarundas/DialogAlert
environment:
sdk: ">=2.15.1 <3.0.0"
flutter: ">=1.17.0"
dependencies:
flutter:
sdk: flutter
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^1.0.0
flutter:
注意三个关键点:
- 没有 plugin: 字段——不是 Flutter 插件,是纯 Dart 包
- 没有 platforms: 声明——没有注册任何平台的原生实现
- dependencies 只有 flutter SDK——零三方原生依赖
虽然 description 写了"native alert view in ios and native alert dialog in android",但 pub.dev 的 description 经常名不副实——看代码不看描述。
第 3 步:MethodChannel 平台通道检查
通过 CDN 读取全部 Dart 源码(lib/ 下两个文件),搜索 MethodChannel、PlatformMessage、BinaryMessenger 等关键词。
show_dialog_alert.dart 的完整核心实现(省略 import 行):
enum ButtonActionType { action, cancel }
Future<ButtonActionType?> showDialogAlert({
required BuildContext context,
required String title,
required String message,
required String actionButtonTitle,
String? cancelButtonTitle,
TextStyle? actionButtonTextStyle,
TextStyle? cancelButtonTextStyle,
}) {
return _showDialogAlert(
context: context,
title: title,
message: message,
actionButtonTitle: actionButtonTitle,
cancelButtonTitle: cancelButtonTitle,
actionButtonTextStyle: actionButtonTextStyle,
cancelButtonTextStyle: cancelButtonTextStyle,
);
}
dialog_alert_button.dart 的完整实现:
class DialogAlertButton extends StatelessWidget {
const DialogAlertButton({
Key? key,
required this.onPressed,
required this.title,
this.isDestructiveAction = false,
this.isDefaultAction = false,
this.textStyle,
}) : super(key: key);
final VoidCallback onPressed;
final String title;
final bool isDestructiveAction;
final bool isDefaultAction;
final TextStyle? textStyle;
Widget build(BuildContext context) {
return !Platform.isIOS
? TextButton(
onPressed: onPressed,
child: Text(
title,
style: textStyle,
),
)
: CupertinoDialogAction(
isDestructiveAction: isDestructiveAction,
isDefaultAction: isDefaultAction,
onPressed: onPressed,
child: Text(
title,
style: textStyle,
),
);
}
}
零 MethodChannel,零平台通道调用。 所有 UI 完全由 Flutter Widget(AlertDialog、TextButton、CupertinoAlertDialog、CupertinoDialogAction)实现。
第 4 步:Platform.isIOS 平台判断检查
两个文件中都有 Platform.isIOS 判断,用于切换 Material / Cupertino 风格。这个判断在 OpenHarmony 上的行为后面第四章详细分析。
第 5 步:依赖递归检查
唯一依赖是 flutter SDK 本身,无递归依赖链风险。
第 6 步:综合判断
| 评估维度 | 结果 |
|---|---|
| 原生平台代码(android/、ios/) | 无 |
| MethodChannel / 平台通道 | 无 |
| pubspec plugin 声明 | 无 |
| 三方原生依赖 | 无 |
| 结论 | 纯 Dart 实现,无需原生适配,可直接用于 OpenHarmony |
关键提醒:pub.dev 的 platforms 字段标注了 Flutter、Android、iOS、Windows 等平台——这个字段不可靠。纯 Dart 包会被 pub.dev 自动标注为全平台支持,不代表它有原生实现。判断的唯一标准是看源码有没有 MethodChannel 和原生目录。
二、适配流程:两处 pubspec 改动 + 一个 ohos 宿主工程
评估结论是"纯 Dart 无需原生适配"后,实际改动非常轻量。
2.1 克隆仓库到本地
原库托管在 GitHub,国内网络直连不稳定,使用 ghproxy 镜像加速:
cd D:\Flutters
git clone https://ghproxy.net/https://github.com/mkarundas/DialogAlert.git dialog_alert
如果你的网络能直连 GitHub,直接用原始地址 git clone https://github.com/mkarundas/DialogAlert.git dialog_alert 即可。
2.2 修改 Dart SDK 版本约束(唯一的代码改动)
这是整个适配过程中唯一需要改代码的地方。
问题:原库 pubspec.yaml 的 SDK 约束是 >=2.15.1 ❤️.0.0,上限锁死在 Dart 2。而 Flutter-OH 3.44.9 搭载的是 Dart 3.12.2,flutter pub get 直接报版本冲突:
Because dialog_alert requires SDK version >=2.15.1 <3.0.0, version solving failed.
修法:把上限从 ❤️.0.0 放宽到 <4.0.0。
修改前(pubspec.yaml 第 6~8 行):
environment:
sdk: ">=2.15.1 <3.0.0"
flutter: ">=1.17.0"
修改后:
environment:
sdk: ">=2.15.1 <4.0.0"
flutter: ">=1.17.0"
example 工程的 pubspec.yaml 同步修改(SDK 约束放宽 + 主包依赖改为本地路径引用)。
修改前:
environment:
sdk: ">=2.15.1 <3.0.0"
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^1.0.2
dialog_alert: ^0.0.2
修改后:
environment:
sdk: ">=2.15.1 <4.0.0"
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^1.0.2
dialog_alert:
path: ../
path: …/ 让 example 直接引用本地修改后的主包,而不是从 pub.dev 拉原版——这样后面的真机验证测的就是我们改过的版本。
为什么原库 4 年没更新? dialog_alert 最后一次发布是 2021 年,当时 Dart 3 还没发布,作者写 ❤️.0.0 完全合理。只是库停更后,新环境(Dart 3)和旧约束之间出现了不兼容。放宽到 <4.0.0 是社区公认的兼容修法,向下兼容 Dart 2,向上兼容 Dart 3。
2.3 创建 OpenHarmony 宿主工程
example 工程原本只有 android/ 和 ios/ 宿主,需要补上 ohos/:
cd D:\Flutters\dialog_alert\example
flutter create --platforms=ohos .
这条命令在 example/ 下生成 ohos/ 目录(约 39 个文件),结构如下:
example/ohos/
├── entry/src/main/
│ ├── module.json5 ← 设备类型声明(下一步要改)
│ ├── ets/entryability/ ← 应用入口 Ability
│ └── resources/ ← 资源文件
├── build-profile.json5 ← 构建配置(签名后会自动写入证书路径)
├── hvigorfile.js ← hvigor 构建脚本
└── oh-package.json5 ← ohpm 包配置
2.4 补全 deviceTypes(鸿蒙 PC 必改项)
flutter create 生成的 module.json5 里,deviceTypes 只有 phone。如果你的目标设备是鸿蒙 PC(2in1 形态)或平板(tablet),必须补全,否则 DevEco Studio 运行时会报设备类型不匹配:
Error Message: The type of target device does not match the device type
configured by module: entry.
Required device type:2in1, current module device type:phone
修改 example/ohos/entry/src/main/module.json5:
{
"module": {
"name": "entry",
"type": "entry",
"deviceTypes": [
"phone",
"tablet",
"2in1"
],
// ... 其余配置保持不变
}
}
经验值:凡是 Flutter-OH 工程(包括三方库适配的 example),deviceTypes 建议 phone、tablet、2in1 三态全声明,一步到位兼容所有鸿蒙设备形态。
三、构建与真机验证
3.1 DevEco Studio 配置调试签名
真机运行 HAP 必须有签名。配置一次即可,后续命令行构建不再需要打开 DevEco。
操作步骤(中文版 DevEco Studio 26 实测菜单路径):
- DevEco Studio →「文件」→「打开」→ 选择 D:\Flutters\dialog_alert\example\ohos(注意是 ohos 子目录,不是 example 根目录,选错找不到签名入口)
- 等右下角工程同步完成
- 「文件」→「项目结构」→ 左侧「签名配置」→ 勾选「自动生成签名」
- 弹出华为账号登录框,登录后证书自动填充,点「确定」
签名信息写入 example/ohos/build-profile.json5。
3.2 运行与构建
在 example 目录下执行:
cd D:\Flutters\dialog_alert\example
flutter run
只连一台设备时不用 -d 参数。hvigor 编译(实测约 38 秒)完成后,应用自动安装到设备并启动。
也可以直接在 DevEco Studio 里点运行按钮,效果一样。DevEco 方式走 IDE 内部的 JDK 构建,不会受系统 JAVA_HOME 版本影响。

3.3 真机效果验证
example 的 main.dart 提供了三个按钮,逐个点击验证:
按钮 1:Simple Alert Dialog
showDialogAlert(
context: context,
title: 'Success',
message: 'You have successfully updated your profile.',
actionButtonTitle: 'OK',
);
预期效果:弹出 Material 风格对话框,标题"Success",正文提示,底部一个"OK"按钮。
按钮 2:Alert Dialog with Cancel Button
final result = await showDialogAlert(
context: context,
title: 'Message',
message: 'Do you want to upload your profile picture?',
actionButtonTitle: 'Upload',
cancelButtonTitle: 'Cancel',
);
预期效果:弹出带"Upload"和"Cancel"两个按钮的对话框。返回值为 ButtonActionType.action 或 ButtonActionType.cancel。
按钮 3:Custom Button Title Text Style
final result = await showDialogAlert(
context: context,
title: 'Success',
message: 'You have successfully uploaded',
actionButtonTitle: 'Submit',
cancelButtonTitle: 'Cancel',
actionButtonTextStyle: const TextStyle(
color: Colors.green,
),
cancelButtonTextStyle: const TextStyle(
color: Colors.pink,
),
);
预期效果:弹出对话框,"Submit"按钮绿色,"Cancel"按钮粉色——验证 TextStyle 自定义参数也能正常传递。
实测结果:三个按钮全部正常弹窗,所有 API 参数工作正常。
验证状态汇总:
| 验证项 | 状态 | 说明 |
|---|---|---|
| 依赖解析(flutter pub get) | ✅ 通过 | Dart 3.12.2 下 SDK 约束冲突已修复 |
| hvigor 编译(flutter build hap) | ✅ 通过 | 实测约 38 秒完成 |
| 真机运行(三个按钮弹窗) | ✅ 通过 | Material 风格,全部 API 工作正常 |

四、源码深度分析:Platform.isIOS 在鸿蒙上的行为
4.1 关键判断逻辑
库内所有平台区分逻辑集中在一个函数里(show_dialog_alert.dart 第 58~73 行):
Future<ButtonActionType?> _showDialogAlertWidget(
BuildContext context, String title, String message, List<Widget> actions) {
if (!Platform.isIOS) {
return showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text(title), content: Text(message), actions: actions));
}
return showCupertinoDialog(
context: context,
builder: (context) => CupertinoAlertDialog(
title: Text(title),
content: Text(message),
actions: actions,
));
}
逻辑很简单:不是 iOS 就走 Material 风格(showDialog + AlertDialog),是 iOS 就走 Cupertino 风格(showCupertinoDialog + CupertinoAlertDialog)。
4.2 OpenHarmony 上的实际走向
dart:io 的 Platform.isIOS 在 OpenHarmony 上恒为 false(鸿蒙不是 iOS 设备),所以代码始终走 Material 分支。
这意味着:
- showDialog() 弹出 Material 风格对话框 → ✅ 正常工作
- AlertDialog 渲染标题、正文、按钮 → ✅ 正常工作
- TextButton 渲染按钮(支持 TextStyle 自定义) → ✅ 正常工作
- Navigator.pop() 返回 ButtonActionType 枚举值 → ✅ 正常工作
Cupertino 风格(CupertinoAlertDialog)在鸿蒙上永远不会触发——这不是缺陷,而是库的设计行为。Android 上也是同样的表现,鸿蒙与 Android 一致。
4.3 按钮侧的同一模式
DialogAlertButton 的 build 方法也是同样的判断:
Widget build(BuildContext context) {
return !Platform.isIOS
? TextButton(
onPressed: onPressed,
child: Text(
title,
style: textStyle,
),
)
: CupertinoDialogAction(
isDestructiveAction: isDestructiveAction,
isDefaultAction: isDefaultAction,
onPressed: onPressed,
child: Text(
title,
style: textStyle,
),
);
}
鸿蒙上走 TextButton 分支,与 Android 行为完全一致。
4.4 为什么纯 Dart 库能直接跨平台
Flutter 的核心设计理念是"一次编写,多端运行"。Material 和 Cupertino 组件都是 Flutter 框架自带的纯 Widget 实现,渲染由 Flutter Engine 的 Skia/Impeller 图形引擎完成,不依赖任何操作系统原生 UI 控件。
所以:
- AlertDialog 不是调用系统的对话框 API,而是 Flutter 自己画的
- TextButton 不是系统的按钮控件,而是 Flutter 自己渲染的
- 只要 Flutter Engine 能在某个平台上跑(OpenHarmony 可以),这些 Widget 就能正常工作
这就是纯 Dart 库无需原生适配的根本原因——它从头到尾都没碰过原生代码。
常见问题 FAQ
Q1:拿到一个 Flutter 库,怎么快速判断它需不需要原生适配?
看 pubspec.yaml 有没有 plugin: platforms: 声明。下面是一个需要原生适配的插件库 pubspec(对比 dialog_alert 的纯 Dart 包 pubspec):
# 需要原生适配的插件库(如 toast、share_plus 等)
flutter:
plugin:
platforms:
android:
pluginClass: ToastPlugin
ios:
pluginClass: ToastPlugin
ohos:
pluginClass: ToastPlugin
dialog_alert 的 pubspec 里没有 plugin: 字段——说明它是纯 Dart 包,不需要写任何原生代码。pub.dev 的 platforms 标签不可靠,纯 Dart 包会被自动标注为全平台支持,判断的唯一标准是看 pubspec 有没有 plugin 声明。
Q2:dialog_alert 的 description 写了"native alert view in ios and native alert dialog in android",为什么实际没有原生代码?
看源码就知道——showDialogAlert 内部用的是 Flutter 自带的 Widget,不是系统原生 API:
// show_dialog_alert.dart 第 58~73 行(真实源码)
if (!Platform.isIOS) {
return showDialog( // Flutter 框架方法
context: context,
builder: (context) => AlertDialog( // Flutter 框架 Widget
title: Text(title), content: Text(message), actions: actions));
}
return showCupertinoDialog( // Flutter 框架方法
context: context,
builder: (context) => CupertinoAlertDialog( // Flutter 框架 Widget
title: Text(title),
content: Text(message),
actions: actions,
));
showDialog、AlertDialog、showCupertinoDialog、CupertinoAlertDialog 全部是 Flutter 框架自带的纯 Widget 实现,渲染由 Flutter Engine 完成,不依赖任何操作系统原生 UI 控件。description 里的"native"是宣传用语,名不副实。
Q3:鸿蒙上弹窗是 Material 风格而不是 Cupertino 风格,算适配缺陷吗?
不算。库内通过 Platform.isIOS 区分风格:
// dialog_alert_button.dart 第 23~39 行(真实源码)
return !Platform.isIOS
? TextButton(...) // Material 风格 → 鸿蒙走这里
: CupertinoDialogAction(...); // Cupertino 风格 → 仅 iOS
鸿蒙上 Platform.isIOS 恒为 false,始终走 TextButton 分支——这和 Android 上的行为完全一致,是库的设计行为,不是适配缺陷。
Q4:如果想练完整的原生适配流程(Kotlin → ArkTS 翻译),应该选什么库?
选 pubspec.yaml 里有 plugin: platforms: 声明且有 MethodChannel 调用的库。比如一个典型的需要完整适配的插件:
# 需要完整原生适配的插件库 pubspec.yaml
flutter:
plugin:
platforms:
android:
pluginClass: VibrationPlugin
ohos:
pluginClass: VibrationPlugin # 需要你在 ArkTS 中实现这个类
对应的 Dart 侧会有 MethodChannel 调用:
// Dart 侧通过 MethodChannel 调用原生能力
static const _channel = MethodChannel('com.example/vibration');
Future<void> vibrate() => _channel.invokeMethod('vibrate');
这类库才需要走完整五阶段:生成 ohos 骨架 → 把 Kotlin/Java 翻译成 ArkTS → 注册 pluginClass → 构建 HAR → 真机验证。典型代表:toast(系统通知)、vibration(振动)、share_plus(系统分享)。
Q5:SDK 约束放宽到 <4.0.0 会不会影响 Dart 2 的兼容性?
不会。看修改前后对比:
# 修改前:只兼容 Dart 2
environment:
sdk: ">=2.15.1 <3.0.0" # 只接受 2.15.1 ~ 2.x.x
# 修改后:同时兼容 Dart 2 和 Dart 3
environment:
sdk: ">=2.15.1 <4.0.0" # 接受 2.15.1 ~ 3.x.x
下限 >=2.15.1 没变,Dart 2 的老项目照样能用;上限从 ❤️.0.0 放宽到 <4.0.0,Dart 3 环境也能解析。这是社区对老库停更后出现版本冲突的标准修法。
Q6:真机运行必须用命令行 flutter run 吗?
不是,两种方式都可以:
# 方式一:命令行(支持热重载)
cd D:\Flutters\dialog_alert\example
flutter run # 按 r 热重载,按 R 热重启,按 q 退出
# 方式二:DevEco Studio 点运行按钮
# 文件 → 打开 → example/ohos → 点运行按钮
DevEco 方式走 IDE 内部的 JDK 构建,不会受系统 JAVA_HOME 版本影响。flutter run 的优势是支持热重载(按 r 秒级刷新),适合开发阶段频繁调试;DevEco 方式适合不习惯命令行的用户。
Q7:deviceTypes 必须三个都写吗?只写 phone 行不行?
只写 phone 在手机上能跑,但换设备就报错:
// ❌ 只声明 phone → 鸿蒙 PC(2in1)和平板上报错
"deviceTypes": ["phone"],
// Error: Required device type:2in1, current module device type:phone
// ✅ 三态全声明 → 一次兼容所有鸿蒙设备形态
"deviceTypes": [
"phone", // 手机
"tablet", // 平板
"2in1" // 鸿蒙 PC
],
建议所有 Flutter-OH 工程都写全三态,避免切换设备时再改。
总结
本文完整记录了 dialog_alert 库从评估到鸿蒙 PC 真机验证的全流程:先通过六步评估法确认它是纯 Dart 实现(无原生目录、无 MethodChannel、无 plugin 声明),然后只做了两处 SDK 约束放宽(pubspec.yaml 的 ❤️.0.0 改为 <4.0.0)+ 一行本地路径依赖(path: …/)+ 一个 flutter create 生成的 ohos 宿主 + 一行 deviceTypes 补全,Dart 层源码零改动,就在鸿蒙 PC 真机上跑通了全部三个对话框弹窗。核心经验:拿到库先花 5 分钟评估类型,纯 Dart 库根本不需要写 ArkTS 代码——动手前查一眼源码,能省掉几小时的无用功。动手前也建议先查一眼 Flutter OH 三方库适配列表,很多热门库已有人适配过,别重复造轮子。
参考资料
更多推荐


所有评论(0)