HarmonyOS Flutter Boost完全接入手册:爬完所有坑的实战指南

Flutter Boost在做混合开发非常实用,但官方文档的不清晰。本文将基于实战经验,帮助大家避开那些常见的坑,快速上手并高效开发。

前言:为何要写这篇手册

在开发过程中,我发现官方文档对于Flutter Boost的集成描述不够清晰,按照官方文档操作会遇到诸多问题。因此,我决定结合自己的实战经验,为大家提供一份详细且实用的集成手册,希望能帮助大家少走弯路。

一、集成问题:从源码到har包的抉择

在开发初期,我尝试通过集成源码来实现热更新等功能,但无论怎么操作,热更新始终无法实现。经过多次尝试和排查,最终只能选择以集成har包的形式进行开发。虽然这种方式不能调试,但运行效果还可以。

如何集成框架

假设你的Flutter模块名为abc_flutter,以下是详细的集成步骤和代码示例:

  1. 修改ohos_app/oh-package.json5

ohos_app/oh-package.json5文件中,添加以下内容:

json 复制代码
{
  "modelVersion": "5.0.4",
  "description": "Please describe the basic information.",
  "dependencies": {
    "@ohos/flutter_module": "file:abc_flutter/.ohos/flutter_module",
    "@ohos/flutter_ohos": "file:abc_flutter/.ohos/har/flutter.har",
    "flutter_boost": "file:abc_flutter/.ohos/har/flutter_boost.har",
  },
  "overrides": {
    "@ohos/flutter_ohos": "file:abc_flutter/.ohos/har/flutter.har",
    "flutter_boost": "file:abc_flutter/.ohos/har/flutter_boost.har",
  },
  "devDependencies": {
    "@ohos/hypium": "1.0.21",
    "@ohos/hamock": "1.0.0"
  }
}

注意事项

  • 第三方库配置:一些flutter的第三方库也需要在这里配置,否则可能会出现编译错误。例如,path_provider_ohos需要添加如下配置:
json 复制代码
  "path_provider_ohos": "file:abc_flutter/.ohos/har/path_provider_ohos.har"
  • 错误示例:如果未正确配置,可能会遇到以下错误:
javascript 复制代码
  1 ERROR: 00309001 ArkTS Compiler Error
  Error Message: Cannot import files outside of the current module using relative paths. Import statement: './src/main/ets/io/flutter/plugins/pathprovider/PathProviderPlugin'. At file: /Users/**/.pub-cache/git/flutter_packages-35fb467533e174411a117b2a030c15d2a3a9687c/packages/path_provider/path_provider_ohos/ohos/index.ets
  1. 修改ohos_app/build-profile.json5

ohos_app/build-profile.json5文件的modules部分添加以下内容:

json 复制代码
{
  "name": "flutter_module",
  "srcPath": "./szxd_flutter/.ohos/flutter_module"
}
  1. 执行命令

执行以下命令来构建har包:

bash 复制代码
fvm flutter build har --debug

二、代码集成:Flutter与UIAbility的深度绑定

在HarmonyOS中,Flutter界面由FlutterPage承载,而整个应用只有一个UIAbility。我们需要在UIAbility的生命周期中绑定Flutter,并初始化Flutter Boost。

  1. Flutter与UIAbility绑定

UIAbilityonCreateonDestroyonWindowStageCreateonWindowStageDestroy生命周期函数中绑定Flutter。以下是代码示例:

typescript 复制代码
export default class EntryAbility extends UIAbility implements FlutterBoostDelegate {
  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
    FlutterManager.getInstance().pushUIAbility(this);
  }

  onWindowStageCreate(windowStage: window.WindowStage): void {
    FlutterManager.getInstance().pushWindowStage(this, windowStage);
  }

  onDestroy(): void {
    FlutterManager.getInstance().popUIAbility(this);
  }

  onWindowStageDestroy(): void {
    FlutterManager.getInstance().popWindowStage(this);
  }
}
  1. 初始化Flutter Boost

onWindowStageCreate中初始化Flutter Boost,并注册插件。以下是代码示例:

typescript 复制代码
export default class EntryAbility extends UIAbility implements FlutterBoostDelegate {
  pushNativeRoute(options: FlutterBoostRouteOptions,
      onPageResult?: ((pageName: string, result: Record<string, Object>) => void) | undefined): void {
    throw new Error('Method not implemented.');
  }

  pushFlutterRoute(options: FlutterBoostRouteOptions,
      onPageResult?: ((pageName: string, result: Record<string, Object>) => void) | undefined): void {
    router.pushUrl({
      url: 'pages/AppFlutterPage', params: {
        uri: options.getPageName(),
        params: JSONUtil.toString(options.getArguments()),
      }
    }).then(() => {
      console.info('Succeeded in jumping to the second page.')
    })
  }

  popRoute(options: FlutterBoostRouteOptions): boolean {
    const pageName = options.getPageName();
    const value = options.getArguments();
    entryLogger.debug(`Pop route called for page: ${pageName}`);

    FlutterBoost.getInstance().sendEventToFlutter(pageName, value);
    return false;
  }

  onWindowStageCreate(windowStage: window.WindowStage): void {
    FlutterManager.getInstance().pushWindowStage(this, windowStage);

    const optionsBuilder: FlutterBoostSetupOptionsBuilder = new FlutterBoostSetupOptionsBuilder();
    FlutterBoost.getInstance().setup(this, this.context, (engine) => {
      GeneratedPluginRegistrant.registerWith(engine);
    }, optionsBuilder.build()).then(() => {
      // 鸿蒙初始化
    });
  }
}

注意事项(敲黑板)

  1. pushFlutterRoute与popRoute的处理
  • pushFlutterRoute:在跳转Flutter页面时,Flutter页面上传的序列化数据可能会丢失。因此,需要在鸿蒙原生中进行数据序列化处理。例如:
typescript 复制代码
  router.pushUrl({
    url: 'pages/AppFlutterPage', params: {
      uri: options.getPageName(),
      params: JSONUtil.toString(options.getArguments()),
    }
  }).then(() => {
    console.info('Succeeded in jumping to the second page.')
  });
  • popRoute:在Flutter页面执行pop后,无法像Flutter原生那样直接获取数据。需要通过sendEventToFlutter方法发送事件,让Flutter页面感知数据。例如:
typescript 复制代码
  FlutterBoost.getInstance().sendEventToFlutter(pageName, value);
  1. 自定义FlutterPage

创建一个FlutterPage,并添加FlutterBoostEntryFlutterView的代码。以下是代码示例:

typescript 复制代码
@Entry
@Component
struct AppFlutterPage {
  private flutterEntry?: FlutterBoostEntry;
  private flutterView?: FlutterView;

  aboutToAppear() {
    let option = router.getParams() as RouterOptions;
    let params = option.params;

    this.flutterEntry = new FlutterBoostEntry(getContext(this), {
      uri: option.uri,
      params: JSON.parse(params as string)
    });

    this.flutterEntry?.aboutToAppear();
    this.flutterView = this.flutterEntry?.getFlutterView();
  }

  aboutToDisappear() {
    this.flutterEntry?.aboutToDisappear();
  }

  onPageShow() {
    this.flutterEntry?.onPageShow();
  }

  onPageHide() {
    this.flutterEntry?.onPageHide();
  }

  onBackPress(): boolean | void {
    FlutterBoost.getInstance()
      .getPlugin()?.onBackPressed();
    return true;
  }

  build() {
    Column() {
      FlutterPage({ viewId: this.flutterView?.getId() })
        .width('100%')
        .height('100%')
    }
    .width('100%')
    .height('100%')
  }
}

注意事项:这里要这么配置,可以保证数据不会丢失 this.flutterEntry = new FlutterBoostEntry(getContext(this), { uri: option.uri, params: JSON.parse(params as string) });

  1. 跳转Flutter界面

在需要跳转Flutter界面时,直接使用router跳转到AppFlutterPage即可。例如:

typescript 复制代码
router.pushUrl({
  url: 'pages/AppFlutterPage', params: {
    uri: '这里写dart侧注册好的路由名',
    params: '传递给界面的参数',
  }
}).then(() => {
  console.info('Succeeded in jumping to the second page.')
});

结语:实战经验的总结

通过上述步骤,可以成功集成Flutter Boost到HarmonyOS项目中。虽然过程中可能会遇到一些坑,但只要按照本文的指南操作,就能顺利解决。希望这篇文章能够帮助大家更好地使用Flutter Boost,提升开发效率

相关推荐
三翼鸟数字化技术团队12 小时前
鸿蒙平台运行Lua脚本
lua·harmonyos
万少13 小时前
学着学着 我就给这个 HarmonyOS 应用增加了些新技术
前端·后端·harmonyos
zhanshuo18 小时前
用 ArkUI 打造媲美小红书的瀑布流布局,原来只需一个 Grid!
harmonyos
生如夏花℡18 小时前
HarmonyOS学习记录5
学习·华为·harmonyos
time never ceases18 小时前
鸿蒙卡片开发保姆级教程
华为·harmonyos·卡片·harmonyosnext
_waylau18 小时前
跟老卫学HarmonyOS开发:HarmonyOS ArkTS 获取位置服务
华为·开源·harmonyos·鸿蒙
ajassi200021 小时前
开源 Arkts 鸿蒙应用 开发(十)通讯--Http数据传输
linux·华为·开源·harmonyos
Chaunceyin1 天前
OpenHarmony之WebSocket开发
网络·websocket·网络协议·harmonyos
ajassi20001 天前
开源 Arkts 鸿蒙应用 开发(九)通讯--tcp客户端
linux·开源·harmonyos
迷曳1 天前
28、鸿蒙Harmony Next开发:不依赖UI组件的全局气泡提示 (openPopup)和不依赖UI组件的全局菜单 (openMenu)、Toast
前端·ui·harmonyos·鸿蒙