
回复
作为一个曾为跨进程界面头疼的开发者,今天要揭秘HarmonyOS的嵌入式UI扩展组件!第一次用它把计算器嵌入聊天界面时,同事以为我用了「界面穿越术」,其实只是掌握了这个跨进程界面嵌入的神器~
想象微信聊天时,不用退出就能呼出计算器:
场景 | 嵌入效果 | 生活类比 |
---|---|---|
工具嵌入 | 聊天界面嵌计算器 | 话剧舞台临时加道具台 |
功能扩展 | 电商详情页嵌客服浮窗 | 剧院边幕加服务生 |
多任务协同 | 文档编辑嵌实时翻译 | 剧本旁放翻译提词器 |
// 计算器扩展组件
import { EmbeddedUIExtensionAbility, UIExtensionContentSession } from '@ohos.app.ability';
export default class CalculatorExtension extends EmbeddedUIExtensionAbility {
onCreate() {
console.log('计算器通道创建');
}
onSessionCreate(want, session) {
console.log('计算器会话创建,准备嵌入');
session.loadContent('pages/calculator', {}); // 加载计算器页面
}
onSessionDestroy(session) {
console.log('计算器通道关闭');
}
}
// module.json5
{
"extensionAbilities": [
{
"name": ".CalculatorExtension",
"src": ["CalculatorExtension.ets"],
"embedded": {
"supportDimensions": ["120px*200px"] // 嵌入窗口尺寸
}
}
]
}
// 聊天界面嵌入计算器
import { Want, EmbeddedComponent } from '@ohos.app.ability';
@Entry
@Component
struct ChatPage {
private embeddedComp: EmbeddedComponent;
build() {
Column {
Text('聊天界面')
.fontSize(20)
// 嵌入计算器组件
EmbeddedComponent({
want: {
bundleName: 'com.example.calculator',
abilityName: 'CalculatorExtension'
},
type: EmbeddedType.EMBEDDED_UI_EXTENSION
})
.width(200)
.height(300)
.margin(10)
}
}
}
// 聊天界面传数据给计算器
AppStorage.SetOrCreate('calcData', {
expression: '1+1',
result: 0
});
// 计算器界面取数据
const calcData = AppStorage.Get('calcData');
this.expression = calcData.expression;
// 聊天界面发事件
import { getContext } from '@ohos.app.ability';
const eventHub = getContext(this).eventHub;
eventHub.publish('calcEvent', { type: 'calculate', data: '1+1' });
// 计算器收事件
eventHub.on('calcEvent', (data) => {
this.calculate(data.data);
});
优势 | 类比 | 开发收益 |
---|---|---|
进程隔离 | 隔音墙,两边互不干扰 | 一方崩溃不影响另一方 |
内存隔离 | 独立仓库,道具不混放 | 内存泄漏不扩散 |
权限隔离 | 独立门锁,权限分开 | 计算器不能访问聊天数据 |
{
"extensionAbilities": [
{
"name": ".SecureExtension",
"src": ["SecureExtension.ets"],
"sandbox": {
"enabled": true, // 开启独立沙箱
"permissions": ["ohos.permission.CALCULATE"] // 单独权限
}
}
]
}
// 计算器页面(被嵌入)
@Entry
@Component
struct Calculator {
@State expression: string = '';
@State result: string = '';
build() {
Column {
Text(this.expression)
.fontSize(24)
.margin(10)
Grid() {
// 计算器按钮布局...
Button('1')
.onClick(() => this.appendToExpression('1'))
// 其他按钮...
}
.columnsTemplate('1fr 1fr 1fr 1fr')
.rowsTemplate('50px 50px 50px 50px')
}
.width('100%')
.height('100%')
}
appendToExpression(value: string) {
this.expression += value;
}
}
// 聊天界面中给嵌入组件加拖拽
EmbeddedComponent({ /* 基础配置 */ })
.gesture(
PanGesture({ direction: GestureDirection.All })
.onActionUpdate((event) => {
// 实时更新位置
this.positionX = event.offsetX;
this.positionY = event.offsetY;
})
)
.translate({ x: this.positionX, y: this.positionY })
onSessionDestroy(session) {
// 销毁时清内存,像通道关门清场
this.clearCachedData();
session.release();
}
优化项 | 做法 | 效果 |
---|---|---|
数据压缩 | 传数据前压缩,像把纸条叠小 | 通信效率+30% |
批量传输 | 攒一批数据再传,像攒够纸条再送 | 减少通道开门次数 |
异步处理 | 通信放后台,像用对讲机传话 | 不阻塞前台界面 |
场景 | 传统开发 | 嵌入式开发 |
---|---|---|
跨进程界面 | 跳转页面,打断流程 | 直接嵌入,流程连续 |
性能影响 | 进程间调用卡顿 | 独立进程不影响 |
安全性 | 数据易泄漏 | 沙箱隔离更安全 |
第一次在聊天界面嵌入计算器时,同事以为我改了系统底层~ 其实只是用对了嵌入式UI扩展组件~ 现在做应用时,常用这个功能做「浮窗工具」,用户说「像有魔法一样方便」~