Flutter跨平台开发:Books 在鸿蒙系统上的使用指南
Flutter Books示例项目展示了如何在原生鸿蒙应用中嵌入Flutter模块,并通过Pigeon插件实现双向通信。该项目模拟了图书目录应用场景,原生部分实现图书列表,Flutter模块负责详情页面。主要特点包括:支持鸿蒙与Flutter的无缝集成、自动生成跨平台API、保持原生架构约束。使用要求Flutter 2.19.5+和HarmonyOS 3.0+环境,通过Git引入依赖后,可在鸿蒙布
1. 插件介绍
Flutter Books 是一个展示如何在现有原生应用中嵌入 Flutter 模块的示例项目,特别演示了如何使用 Pigeon 插件在 Flutter 和宿主应用之间进行高效通信。
这个示例项目模拟了一个真实的图书目录应用场景:
- 现有原生鸿蒙应用已经实现了图书列表功能
- 使用 Flutter 实现一个新的图书详情页面
- 通过 Pigeon 实现 Flutter 与鸿蒙原生代码之间的无缝数据交互
- 保持原生应用的现有中间件约束,确保技术栈一致性
2. 插件功能特性
- 支持在鸿蒙应用中嵌入 Flutter 模块
- 使用 Pigeon 自动生成跨平台互操作 API 和数据类
- 实现 Flutter 与鸿蒙原生之间的双向通信
- 保持原生应用的开发模式和架构约束
- 支持图书信息的展示和编辑功能
- 提供完整的示例代码,展示真实场景下的集成方案
3. 快速开始
3.1 环境要求
- Flutter SDK 2.19.5 或更高版本
- HarmonyOS SDK 3.0 或更高版本
- DevEco Studio 3.0 或更高版本
- JDK 11 或更高版本
3.2 引入依赖
由于这是一个自定义修改版本的三方库,需要通过 Git 形式引入。在项目的 pubspec.yaml 文件中添加以下配置:
dependencies:
flutter:
sdk: flutter
flutter_module_books:
git:
url: "https://atomgit.com/flutter/samples.git"
path: "add_to_app/books/flutter_module_books"
dev_dependencies:
pigeon: ^11.0.0
然后运行以下命令获取依赖:
flutter pub get
4. 使用方法
4.1 鸿蒙应用中嵌入 Flutter 图书详情页面
- 在鸿蒙应用的布局文件中添加 Flutter 视图容器:
<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayout
xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:height="match_parent"
ohos:width="match_parent"
ohos:orientation="vertical">
<!-- 鸿蒙原生图书列表 -->
<ListContainer
ohos:id="$+id:book_list"
ohos:height="match_parent"
ohos:width="match_parent"
ohos:orientation="vertical"/>
</DirectionalLayout>
- 在鸿蒙应用的 AbilitySlice 中初始化图书列表并处理点击事件:
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.aafwk.content.Operation;
import ohos.agp.components.Component;
import ohos.agp.components.ListContainer;
import ohos.agp.components.Text;
import java.util.ArrayList;
import java.util.List;
public class MainAbilitySlice extends AbilitySlice {
private List<Book> bookList = new ArrayList<>();
@Override
public void onStart(Intent intent) {
super.onStart(intent);
super.setUIContent(ResourceTable.Layout_ability_main);
// 初始化图书数据
initBookData();
// 设置列表容器
ListContainer listContainer = (ListContainer) findComponentById(ResourceTable.Id_book_list);
BookAdapter adapter = new BookAdapter(this, bookList);
listContainer.setItemProvider(adapter);
// 处理列表项点击事件
listContainer.setItemClickedListener((listContainer1, component, position, id) -> {
Book selectedBook = bookList.get(position);
openFlutterBookDetails(selectedBook);
});
}
private void initBookData() {
// 模拟从API获取图书数据
Book book1 = new Book();
book1.setTitle("Flutter实战");
book1.setAuthor("冷启动");
book1.setSubtitle("基于Flutter 2.0的应用开发实践");
book1.setSummary("本书详细介绍了Flutter的核心概念和开发技巧...");
book1.setPublishDate("2021-06-01");
book1.setPageCount(420);
Thumbnail thumbnail1 = new Thumbnail();
thumbnail1.setUrl("https://example.com/flutter_book.jpg");
book1.setThumbnail(thumbnail1);
bookList.add(book1);
// 添加更多图书...
}
private void openFlutterBookDetails(Book book) {
// 创建跳转到Flutter图书详情页面的意图
Intent intent = new Intent();
Operation operation = new Intent.OperationBuilder()
.withDeviceId("")
.withBundleName("dev.flutter.example.harmonyos_books")
.withAbilityName("FlutterBookAbility")
.build();
intent.setOperation(operation);
// 通过Intent传递图书数据
intent.setParam("book", book);
// 启动Flutter图书详情页面
startAbilityForResult(intent, 1001);
}
@Override
protected void onAbilityResult(int requestCode, int resultCode, Intent resultData) {
super.onAbilityResult(requestCode, resultCode, resultData);
if (requestCode == 1001 && resultCode == RESULT_OK) {
// 处理从Flutter返回的编辑后的图书数据
Book editedBook = resultData.getParam("editedBook", Book.class);
updateBookInList(editedBook);
}
}
private void updateBookInList(Book editedBook) {
// 更新图书列表中的数据
for (int i = 0; i < bookList.size(); i++) {
if (bookList.get(i).getTitle().equals(editedBook.getTitle())) {
bookList.set(i, editedBook);
break;
}
}
// 刷新列表
ListContainer listContainer = (ListContainer) findComponentById(ResourceTable.Id_book_list);
((BookAdapter) listContainer.getItemProvider()).notifyDataChanged();
}
}
4.2 创建 Flutter 图书详情 Ability
- 在鸿蒙应用中创建一个新的 Ability 来承载 Flutter 视图:
import com.huawei.flutter.hmos.adapter.FlutterView;
import ohos.aafwk.ability.Ability;
import ohos.aafwk.content.Intent;
import ohos.agp.components.ComponentContainer;
import ohos.agp.window.dialog.ToastDialog;
import java.util.HashMap;
import java.util.Map;
public class FlutterBookAbility extends Ability {
private FlutterView flutterView;
private Book currentBook;
@Override
public void onStart(Intent intent) {
super.onStart(intent);
super.setUIContent(ResourceTable.Layout_ability_flutter_book);
// 获取传递过来的图书数据
currentBook = intent.getParam("book", Book.class);
// 初始化 FlutterView
ComponentContainer container = (ComponentContainer) findComponentById(ResourceTable.Id_flutter_container);
flutterView = new FlutterView(this);
flutterView.setBundleName("dev.flutter.example.flutter_module_books");
flutterView.setEntrypoint("main");
container.addComponent(flutterView);
// 初始化 Flutter 引擎
flutterView.initialize();
// 注册 Pigeon API
registerPigeonApi();
// 向 Flutter 传递图书数据
sendBookToFlutter();
}
private void registerPigeonApi() {
// 注册 HostBookApi 实现
HostBookApi.setup(flutterView.getFlutterEngine().getDartExecutor().getBinaryMessenger(), new HostBookApi() {
@Override
public void cancel() {
// 处理取消操作
terminateAbility();
}
@Override
public void finishEditingBook(Book editedBook) {
// 处理编辑完成的图书数据
Intent resultIntent = new Intent();
resultIntent.setParam("editedBook", editedBook);
setResult(RESULT_OK, resultIntent);
terminateAbility();
}
});
}
private void sendBookToFlutter() {
// 获取 FlutterBookApi 实例
FlutterBookApi flutterApi = FlutterBookApi.getApi(flutterView.getFlutterEngine().getDartExecutor().getBinaryMessenger());
// 向 Flutter 发送图书数据
flutterApi.displayBookDetails(currentBook, new PigeonReply<Void>() {
@Override
public void reply(Void reply) {
// 处理发送成功的回调
}
@Override
public void error(String errorCode, String errorMessage, Object errorDetails) {
// 处理发送失败的回调
new ToastDialog(FlutterBookAbility.this)
.setText("Failed to send book data to Flutter: " + errorMessage)
.show();
}
});
}
@Override
protected void onForeground(Intent intent) {
super.onForeground(intent);
if (flutterView != null) {
flutterView.onForeground();
}
}
@Override
protected void onBackground() {
super.onBackground();
if (flutterView != null) {
flutterView.onBackground();
}
}
@Override
protected void onStop() {
super.onStop();
if (flutterView != null) {
flutterView.onStop();
}
}
}
4.3 Flutter 模块开发
- 使用 Pigeon 生成的 API 在 Flutter 中显示图书详情:
import 'package:flutter/material.dart';
import 'package:flutter_module_books/api.dart';
void main() {
runApp(BookDetailsApp());
}
class BookDetailsApp extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
title: '图书详情',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: BookDetailsScreen(),
);
}
}
class BookDetailsScreen extends StatefulWidget {
_BookDetailsScreenState createState() => _BookDetailsScreenState();
}
class _BookDetailsScreenState extends State<BookDetailsScreen> {
Book? _currentBook;
final TextEditingController _titleController = TextEditingController();
final TextEditingController _authorController = TextEditingController();
final TextEditingController _summaryController = TextEditingController();
void initState() {
super.initState();
// 注册 FlutterBookApi 实现
FlutterBookApi.setup(FlutterBookApiImpl(this));
}
void setBook(Book book) {
setState(() {
_currentBook = book;
_titleController.text = book.title ?? '';
_authorController.text = book.author ?? '';
_summaryController.text = book.summary ?? '';
});
}
Widget build(BuildContext context) {
if (_currentBook == null) {
return Scaffold(
appBar: AppBar(title: Text('图书详情')),
body: Center(child: CircularProgressIndicator()),
);
}
return Scaffold(
appBar: AppBar(
title: Text('图书详情'),
actions: [
IconButton(
icon: Icon(Icons.save),
onPressed: () => saveChanges(),
),
],
),
body: SingleChildScrollView(
padding: EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (_currentBook?.thumbnail?.url != null)
Image.network(
_currentBook!.thumbnail!.url!,
height: 200,
width: double.infinity,
fit: BoxFit.cover,
),
SizedBox(height: 16.0),
TextField(
controller: _titleController,
decoration: InputDecoration(labelText: '书名'),
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
),
SizedBox(height: 8.0),
TextField(
controller: _authorController,
decoration: InputDecoration(labelText: '作者'),
),
SizedBox(height: 8.0),
TextField(
controller: _summaryController,
decoration: InputDecoration(labelText: '简介'),
maxLines: null,
),
SizedBox(height: 16.0),
Text('出版日期: ${_currentBook?.publishDate ?? '未知'}'),
Text('页数: ${_currentBook?.pageCount ?? '未知'}'),
],
),
),
);
}
void saveChanges() {
// 创建编辑后的图书对象
Book editedBook = Book()
..title = _titleController.text
..author = _authorController.text
..summary = _summaryController.text
..subtitle = _currentBook?.subtitle
..publishDate = _currentBook?.publishDate
..pageCount = _currentBook?.pageCount
..thumbnail = _currentBook?.thumbnail;
// 调用 Host API 完成编辑
HostBookApi api = HostBookApi();
api.finishEditingBook(editedBook);
}
}
class FlutterBookApiImpl extends FlutterBookApi {
final _BookDetailsScreenState _state;
FlutterBookApiImpl(this._state);
void displayBookDetails(Book book) {
_state.setBook(book);
}
}
5. 使用 Pigeon 生成 API
Pigeon 是一个用于生成跨平台互操作代码的工具,可以自动创建 Flutter 与原生代码之间的通信层。以下是如何使用 Pigeon 的步骤:
5.1 创建 Pigeon Schema
在 Flutter 模块中创建 pigeon/schema.dart 文件,定义数据模型和 API 接口:
import 'package:pigeon/pigeon.dart';
class Book {
String? title;
String? subtitle;
String? author;
String? summary;
String? publishDate;
int? pageCount;
Thumbnail? thumbnail;
}
class Thumbnail {
String? url;
}
()
abstract class FlutterBookApi {
void displayBookDetails(Book book);
}
()
abstract class HostBookApi {
void cancel();
void finishEditingBook(Book book);
}
5.2 生成互操作代码
运行以下命令生成 Flutter 与鸿蒙原生之间的互操作代码:
flutter pub run pigeon --input pigeon/schema.dart \
--dart_out lib/api.dart \
--java_out ../harmonyos_books/entry/src/main/java/dev/flutter/example/books/Api.java \
--java_package "dev.flutter.example.books"
这将生成以下文件:
lib/api.dart- Flutter 侧的 API 代码Api.java- 鸿蒙原生侧的 API 代码
6. 构建与运行
6.1 构建 Flutter 模块
在 Flutter 模块目录下运行以下命令构建 Flutter AAR:
flutter build aar --no-debug --no-profile
6.2 构建鸿蒙应用
在 DevEco Studio 中打开鸿蒙应用项目,然后点击 “Build” -> “Build HAP(s)/APP(s)” -> “Build APP(s)” 构建完整的鸿蒙应用。
6.3 运行应用
将鸿蒙设备连接到开发机,然后在 DevEco Studio 中点击 “Run” 按钮或使用以下命令运行应用:
hap build install
7. 常见问题与解决方案
7.1 Flutter 视图无法加载
问题:鸿蒙应用中 Flutter 视图显示为空白或无法加载。
解决方案:
- 检查 Flutter SDK 版本是否符合要求(2.19.5 或更高)
- 确保 Flutter 模块已正确构建(运行
flutter build aar) - 检查鸿蒙应用的
config.json文件中是否已配置 Flutter 相关权限 - 查看日志获取详细错误信息:
hdc shell logcat -s Flutter
7.2 Pigeon API 调用失败
问题:Flutter 与鸿蒙原生之间的 Pigeon API 调用失败。
解决方案:
- 确保已正确生成 Pigeon API 代码
- 检查 API 接口名称和参数是否匹配
- 确保已在两侧正确注册 API 实现
- 查看日志获取详细错误信息
7.3 性能问题
问题:嵌入 Flutter 视图后,鸿蒙应用的性能下降。
解决方案:
- 避免在同一屏幕上嵌入过多 Flutter 视图
- 优化 Flutter 代码,减少不必要的重建和重绘
- 合理使用 Flutter 的异步加载和缓存机制
- 考虑使用 Flutter 的 release 模式构建应用(
flutter build aar --release)
8. 总结
Flutter Books 示例项目展示了如何在鸿蒙系统上实现 Flutter 与原生应用的无缝集成,特别是通过 Pigeon 插件实现高效的数据通信。
通过本文的指南,您已经了解了如何:
- 在现有鸿蒙应用中嵌入 Flutter 模块
- 使用 Pigeon 生成跨平台互操作代码
- 实现 Flutter 与鸿蒙原生之间的双向通信
- 构建和运行混合应用
这种集成方式允许开发者在保持现有应用架构和技术栈的同时,利用 Flutter 的跨平台能力快速开发新功能,为鸿蒙应用开发提供了更大的灵活性和效率。
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
更多推荐


所有评论(0)