Flutter鸿蒙终端一体化-天下一统

news2024/12/24 1:01:13

在前面的文章中,我们了解了如何使用FlutterPage来创建Flutter容器。

Flutter鸿蒙终端一体化-混沌初开

Flutter鸿蒙终端一体化-珠联璧合 · 语雀

但更多的时候,我们需要的是一种类似FlutterFragment的方式来进行引用,可喜的是,鸿蒙实现这种方式也并不复杂,因为不论是FlutterPage,还是FlutterFragment,它内部实际上是通过FlutterView的方式来创建的,所以,很快就有开发者提了PR,让鸿蒙可以支持FlutterFragment的方式进行开发,这个组件就是——FlutterEntry,原始PR地址如下。
gitee.com/openharmony…

使用还是相当简单的,添加生命周期的依赖注入即可。
 

image.png


 

image.png

和FlutterPage的使用很类似,FlutterEntry也提供了getDartEntrypointArgs、configureFlutterEngine等方法,仿照Native的封装思路,我们也封装下FlutterEntry。

 

arkts

复制代码

import FlutterEntry from '@ohos/flutter_ohos/src/main/ets/embedding/ohos/FlutterEntry'; import FlutterEngine from '@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterEngine'; import MethodChannel, { MethodCallHandler, MethodResult } from '@ohos/flutter_ohos/src/main/ets/plugin/common/MethodChannel'; import MethodCall from '@ohos/flutter_ohos/src/main/ets/plugin/common/MethodCall'; import { NativeNetApi, NativeNetApiImp } from './NetChannel'; export default class BaseFlutterEntry extends FlutterEntry implements MethodCallHandler { private channel: MethodChannel | null = null; routeParams: string = ''; constructor(context: Context, routeParams: string) { super(context); this.routeParams = routeParams } getDartEntrypointArgs(): string[] { let map = new Map<string, string>() map.set('xxx', 'xxx') map.set('xxx', this.routeParams) return new Array(this.mapToString(map)); } mapToString(map: Map<string, string>): string { if (map.size === 0) { return ''; } let obj: object = new Object; map.forEach((value, key) => { obj[key] = value; }) return JSON.stringify(obj); } configureFlutterEngine(flutterEngine: FlutterEngine): void { this.channel = new MethodChannel(flutterEngine.dartExecutor.getBinaryMessenger(), 'com.xxx.flutter.method_call'); this.channel?.setMethodCallHandler(this); NativeNetApi.setup(flutterEngine.dartExecutor, new NativeNetApiImp()) } onMethodCall(call: MethodCall, result: MethodResult): void { switch (call.method) { case 'testChannel': result.success('Harmony') break; } } }

在这两个关键方法中,我们实现了Native到鸿蒙的参数传递,以及Channel的封装,MethodChannel和Native一样,直接实现接口即可,自定义Channel,可以通过鸿蒙版的pigeon来实现(后面我们单独来讲)。

接下来再封装一个布局,用于承载这个FlutterEntry。

 

arkts

复制代码

import Log from '@ohos/flutter_ohos/src/main/ets/util/Log'; import { FlutterView } from '@ohos/flutter_ohos/src/main/ets/view/FlutterView'; import { FlutterPage } from '@ohos/flutter_ohos'; import BaseFlutterEntry from '../maintabability/flutter/BaseFlutterEntry'; @Entry @Component export struct FlutterEntryIndex { private flutterEntry: BaseFlutterEntry | null = null; private flutterView?: FlutterView params: string = ''; aboutToAppear() { this.flutterEntry = new BaseFlutterEntry(getContext(this), this.params) this.flutterEntry.aboutToAppear() this.flutterView = this.flutterEntry.getFlutterView() Log.d("Flutter", "Index aboutToAppear==="); } aboutToDisappear() { Log.d("Flutter", "Index aboutToDisappear==="); this.flutterEntry?.aboutToDisappear() } onPageShow() { Log.d("Flutter", "Index onPageShow==="); this.flutterEntry?.onPageShow() } onPageHide() { Log.d("Flutter", "Index onPageHide==="); this.flutterEntry?.onPageHide() } build() { Stack() { FlutterPage({ viewId: this.flutterView?.getId() }) } } }

这里和官方示例的区别主要是参数的传递和FlutterEntry的封装,其它都没有变化。

最后,我们需要在承载FlutterEntry的Ability中添加相关的生命周期处理。

 

arkts

复制代码

import AbilityConstant from '@ohos.app.ability.AbilityConstant'; import hilog from '@ohos.hilog'; import UIAbility from '@ohos.app.ability.UIAbility'; import Want from '@ohos.app.ability.Want'; import window from '@ohos.window'; import FlutterManager from '@ohos/flutter_ohos/src/main/ets/embedding/ohos/FlutterManager'; export default class MainAbility extends UIAbility { onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate'); FlutterManager.getInstance().pushUIAbility(this) } onDestroy(): void { hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy'); FlutterManager.getInstance().popUIAbility(this) } onWindowStageCreate(windowStage: window.WindowStage): void { // Main window is created, set main page for this ability hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); windowStage.getMainWindowSync().setWindowLayoutFullScreen(true, () => { }) windowStage.loadContent('pages/xxxx', (err, data) => { if (err.code) { hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); return; } hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? ''); }); FlutterManager.getInstance().pushWindowStage(this, windowStage) } onWindowStageDestroy(): void { // Main window is destroyed, release UI related resources hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy'); FlutterManager.getInstance().popWindowStage(this) } onForeground(): void { // Ability has brought to foreground hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground'); } onBackground(): void { // Ability has back to background hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground'); } }

以及它的布局文件(省略了一些代码)。

 

arkts

复制代码

import { FlutterEntryIndex } from './FlutterEntryIndex' @Entry @Component export struct xxxx { @State currentTabIndex: number = 1 private tabsController: TabsController = new TabsController(); build() { Navigation(this.mainNavStack) { Tabs({ index:this.currentTabIndex, controller:this.tabsController }) { TabContent() { XXXX() } .tabBar(this.bar('xxx', $r('xxxxx'), 0)) TabContent() { FlutterEntryIndex({params:'XXXXPage'}) } .tabBar(this.bar('xxx', $r('xxxxxx'), 1)) TabContent() { FlutterEntryIndex({params:'XXXXPage'}) } .tabBar(this.bar('xxx', $r('xxxxxx'), 2)) } .onChange((index) => { this.currentTabIndex = index }) } }

至此,我们基本跑通了Flutter在鸿蒙的各种场景,以及Flutter和鸿蒙之间的通信。

鸿蒙的支持还是很快的,当前Flutter稳定在3.7版本,这个版本算是一个中规中矩的官方版本,既不会太陈旧,也不会太新,没有引入Dart3.0,以及新的渲染引擎的适配,所以整体性能可以得到保证的同时,也可以让Flutter开发者减少对鸿蒙的适配。

相对于Native开发来说,在鸿蒙中使用Flutter是相对简单的,毕竟少了很多生命周期的管理和适配,统一基于FlutterView来实现,整体性能可控,同时鸿蒙申明式的UI创建方式,和Flutter也保持同步,在开发思路上能更加的符合,当然更重要的是,鸿蒙摈弃了Android的一些历史问题导致的bug,可以基于一个全新的系统来适配,其潜力可想而知。

遥遥领先,确实有点东西。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1814680.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

稳定性测试要点+性能监控关键指标分析

前言 1、稳定性测试的要点 1&#xff09;长时间的以正常的业务负载进行运行&#xff08;最低为用户实际使用时的负载量&#xff0c;如果用户实际负载量低于最优负载量&#xff0c;也可以使用最优负载量&#xff09; 2&#xff09;稳定性的测试数据&#xff08;用户实际使用负…

文献解读-农业系列-第八期|《有害突变在多倍体棉花中积累速度快于二倍体棉花,且在亚基因组间不平衡》

关键词&#xff1a;基因组变异检测&#xff1b;全基因组测序&#xff1b;基因组多倍体化&#xff1b; 文献简介 标题&#xff08;英文&#xff09;&#xff1a;Deleterious Mutations Accumulate Faster in Allopolyploid Than Diploid Cotton (Gossypium) and Unequally betw…

【笔记】深度学习入门

神经网络基础 计算机视觉 1.1 人工智能的本质——线性模型 ykxb k为权重&#xff0c;b为偏置 像素点有323233072个任务点 所以权重有3072个&#xff0c;假设有10组类别&#xff0c;注意权重是一个矩阵 1.2 模型更新方法 权重一开始是随机的 权重和损失值&#xff0c;尝试…

进口电动对夹式硬密封蝶阀的特点-美国品牌

进口电动对夹式硬密封蝶阀的特点可以归纳如下&#xff1a; 一、结构特点 对夹式设计&#xff1a;采用对夹式连接&#xff0c;无需法兰和螺栓&#xff0c;安装简便快捷&#xff0c;降低了安装成本和空间占用。三偏心结构&#xff1a;阀座与蝶板之间采用三偏心设计&#xff0c;…

外汇天眼:Equals集团发布战略评估通知:MDP不再考虑收购提议

Equals Group plc (LON)今天发布了一份关于其战略评估的通知。 Equals公司不再与Madison Dearborn Partners, LLC (MDP)就公司的收购提议进行讨论。MDP因此发布了一份声明&#xff0c;确认其不打算为公司提出收购提议。 然而&#xff0c;MDP与其投资组合公司MoneyGram Interna…

Codeforces Round 950 (Div. 3) A~F

A.Problem Generator&#xff08;遍历&#xff09; 题意&#xff1a; 弗拉德计划在下个月举行 m m m轮比赛。每轮比赛应包含一个难度为"A"、“B”、“C”、“D”、“E”、"F"和"G"的问题。 弗拉德已经有了一个 n n n个问题的问题库&#xff0…

开发文档 RAG 的 GPTs 如何更高效地帮你 AI 编程?

&#xff08;注&#xff1a;本文为小报童精选文章。已订阅小报童或加入知识星球「玉树芝兰」用户请勿重复付费&#xff09; 某些看似门槛很高的专业技能&#xff0c;在 AI 冲击下居然那么脆弱。 需求 自从有了ChatGPT&#xff0c;我拿它编程很久了。今年春季学期的《深度学习》…

计算机信息安全技术课后习题答案

计算机信息安全技术课后习题答案 计算机信息安全技术&#xff08;第2版&#xff09;付永刚 部分习题答案 第一章 计算机信息安全技术概述 选择题 关于访问控制服务的描述中&#xff0c;正确的是&#xff08; A &#xff09; A. 可控制用户访问网络资源 B.可识别发送方的真实身…

STM32无法烧写程序的故障排除

如果你在使用STM32微控制器时遇到无法烧写程序的问题&#xff0c;可以按以下步骤进行故障排除&#xff1a; 1. 确认硬件连接 检查电源&#xff1a;确保STM32板子正确供电。调试器连接&#xff1a;确认ST-LINK调试器或其他编程工具与STM32开发板的连接无误&#xff0c;尤其是S…

将web项目打包成electron桌面端教程(二)vue3+vite+ts

说明&#xff1a;我用的demo项目是vue3vitets&#xff0c;如果是vue2/cli就不用往下看啦&#xff0c;建议找找其他教程哦~下依赖npm下载不下来的&#xff0c;基本换成cnpm/pnpm/yarn就可以了 一、项目准备 1、自己新创建一个&#xff0c;这里就不过多赘述了 2、将需要打包成…

windows上修改Podman的镜像配置源加速

目录 前言解决办法1. 打开window的Powershell 2. 修改registries.conf3. 重启podman即可 扩展内容1. 国内镜像源地址2. 阿里加速地址 前言 今天在电脑上准备通过podman安装mysql&#xff0c;结果执行安装命令后&#xff0c;网络不通没法下载镜像。 解决办法 将默认镜像源修改…

AI 大模型训练中,通常会采用哪些方法?(输入篇)

大家好 某种程度来说大模型训练的核心算法就是300到400行代码&#xff0c;如果真正理解了并不难。下面我将带大家分析常规大模型训练有几个阶段以及在训练中一般会用到哪些方法。 由上图可以看出&#xff0c;大模型训练主要有四个阶段&#xff1a;预训练、有监督微调、奖励建模…

C++11:可变参数模板 emplace_back

可变参数模板 基本概念&#xff1a;C 的参数模板是 C11 引入的特性&#xff0c;它允许模板接受可变数量的参数 // Args是一个模板参数包&#xff0c;args是一个函数形参参数包 // 声明一个参数包Args... args&#xff0c;这个参数包中可以包含0到N个模板参数。 template <…

Vue21-列表排序

一、需求 二、解决方式 <body><div id"root"><h2>人员列表</h2><input type"text" placeholder"请输入" v-model"keyword"><button click"sortType 1">年龄升序</button><b…

uniapp地图导航

我们只需要给图标加一个点击事件 我这里的数据都是动态的&#xff0c;想测试的朋友可以写固定值 然后跳转之后首先会调到选择软件导航 点击导航之后会显示使用哪个app 最后我们选择之后将会直接跳转到app进行导航

spring boot3登录开发-邮件验证码接口实现

⛰️个人主页: 蒾酒 &#x1f525;系列专栏&#xff1a;《spring boot实战》 目录 写在前面 上文衔接 接口设计与实现 1.接口分析 2.实现思路 3.代码实现 1.定义验证码短信HTML模板枚举类 2.定义验证码业务接口 3. 验证码业务接口实现 4.控制层代码 4.测试 写…

带你走进信息安全软件架构

汽车行业网联化以及网络安全风险日益突出&#xff0c;汽车网络攻击&#xff0c;漏洞日益增加&#xff0c;危害防不胜防。汽车信息安全逐步受到重视&#xff0c;网络安全相关法律法规陆续颁布。在这样的背景下&#xff0c;AUTOSAR 组织也发布了有关信息安全模块和 Crypto Stack(…

【ARM Coresight Debug 系列 -- ARMv8/v9 软件实现断点地址设置】

请阅读【嵌入式开发学习必备专栏 】 文章目录 ARMv8/v9 软件设置断点地址断点地址软件配置流程代码实现 ARMv8/v9 软件设置断点地址 在ARMv8/9架构中&#xff0c;可以通过寄存器 DBGBVR0_EL1 设置断点。这个寄存器是一系列调试断点值寄存器中的第一个DBGBVRn_EL1&#xff0c;其…

Chromium源码阅读:深入理解Mojo框架的设计思想,并掌握其基本用法(1)

Mojo简介 Mojo 是一个运行时库的集合&#xff0c;提供与平台无关的通用 IPC 原语抽象、消息 IDL 格式以及具有针对多种目标语言的代码生成的绑定库&#xff0c;以便于跨任意进程间和进程内边界传递消息。 Mojo 分为清晰分离的层&#xff0c;子组件的基本层次结构如下&#xff…

GraphQL(7):ConstructingTypes

1 使用GraphQLObjectType 定义type&#xff08;类型&#xff09; 不使用ConstructingTypes定义方式如下&#xff1a; 使用ConstructingTypes定义方式如下&#xff1a; 更接近于构造函数方式 var AccountType new graphql.GraphQLObjectType({name: Account,fields: {name: …