写点什么

【HarmonyOS NEXT】EventHub 和 Emitter 的使用场景与区别

作者:GeorgeGcs
  • 2025-03-26
    上海
  • 本文字数:2953 字

    阅读完需:约 10 分钟

【HarmonyOS NEXT】EventHub和Emitter的使用场景与区别

一、EventHub 是什么?

移动应用开发的同学应该比较了解 EventHub,类似于 EventBus。标准的事件广播通知,订阅,取消订阅的处理。EventHub 模块提供了事件中心,提供订阅、取消订阅、触发事件的能力。


类似的框架工具有很多,例如 MQTT。使用起来也超级简单,从介绍上就能大体了解使用方式,见名知意的一种快捷工具。通过一个事件 ID 即 TAG 作为唯一的 key,进行事件广播通知和订阅。


在 ArkUI 框架中,EventHub 通过单例对象的形式提供,因为放在上下文里。所以每个 UIAbility 对应一个 EventHub。不同的 UIAbility 的 EventHub 是不同步的。


从上下文获取 EventHub 有两种方式:


  1. 在 UIAbility 中直接通过 context 获取:


import { UIAbility, Context, Want, AbilityConstant } from '@kit.AbilityKit';
export default class EntryAbility extends UIAbility { onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { // 获取eventHub let eventhub = this.context.eventHub; }); }}
复制代码


  1. 在 page 界面或者组件中,通过 UIcontext 强转为 UIAbilityContext 获取:


let context = getContext(this) as common.UIAbilityContext;let eventhub = context.eventHub;
复制代码


获得到 EventHub 单例对象后,就可以调用 emit 发送事件,on 监听事件,off 取消监听事件。进行事件广播的使用。


  // TAG作为事件的id为字符串类型  private EVENT_TAG: string = "TEST";    /**   * EventHub事件回调   */  callbackByEventHub = (content: string)=>{    promptAction.showToast({      message: JSON.stringify(content)    });  }  this.eventHub?.on(this.EVENT_TAG, this.callbackByEventHub); this.eventHub?.off(this.EVENT_TAG, this.callbackByEventHub);this.eventHub?.off(this.EVENT_TAG);// 第二个参数不传,则代表EVENT_TAG下的所有注册回调都清空
复制代码


详情参见官网,示例 DEMO 参见最后章节:UIAbility组件与UI的数据同步EventHub API文档

二、Emitter 是什么?

类似于 EventHub 的使用,只是内部封装了事件队列和分发的机制。多了事件 id 和优先级的概念。并且 Emitter 也可以在不同线程内调用。


Emitter 区别于上文中的 EventHub 的事件 ID,定义了一层对象进行约束。除了事件 id,还需要设置事件级别。


  private event: emitter.InnerEvent = {    eventId: this.eventId,    priority: emitter.EventPriority.LOW   // 定义一个eventId为1的事件,事件优先级为Low  };
复制代码


事件级别分为以下几种类型:



和 EventHub 不同的是,事件广播的内容,也进行了约束。 发送事件时传递的数据,支持数据类型包括 Array、ArrayBuffer、Boolean、DataView、Date、Error、Map、Number、Object、Primitive(除了 symbol)、RegExp、Set、String、TypedArray,数据大小最大为 16M。


data 是 key val 形式的对象,可以自己定义里面的 key 和 val。


    let eventData: emitter.EventData = {      data: {        content: '测试数据',        id: 1,        isEmpty: false      }    };
复制代码


事件的广播发送,订阅和取消订阅与 EventHub 区别不大。只是多了 once 一次性监听而已。


  private callback = (eventData: emitter.EventData): void => {
};
emitter.emit(this.event, eventData); emitter.once(this.event, this.callback) emitter.off(this.event.eventId, this.callback);
复制代码


详情参见官网,示例 DEMO 参见最后章节:使用Emitter进行线程间通信EventHub API文档

三、EventHub 和 Emitter 的使用场景与区别

  1. EventHub 是线程内使用的时间广播工具,Emitter 是线程间通信使用的工具

  2. EventHub 的使用更简单,属于轻量级的广播工具,主要用于 UIAbility 和 page 之间,page 和组件之间,组件和组件之间,UI 和 VM 之间的通信,传递的数据内容形式多变且方便(...args: Object[])。Emitter 属于重量级的广播工具,封装了优先级和队列的逻辑。传递的数据内容,必须有包裹成进行约束(emitter.EventData)

  3. Emitter 监听设置,在 on 基础上,额外提供了 once 一次性监听的 API。触发之后不需要再手动 off 取消监听。EventHub 则没有。

源码 DEMO 解析:

import { emitter } from '@kit.BasicServicesKit';import { common } from '@kit.AbilityKit';import { promptAction } from '@kit.ArkUI';
@Entry@Componentstruct EventHubAndEmitterTestPage {
// --------------- EventHub private context = getContext(this) as common.UIAbilityContext; private eventHub: common.EventHub | null = null; private EVENT_TAG: string = "TEST";
private emitByEventHub(){ this.eventHub = this.context.eventHub; this.eventHub.emit(this.EVENT_TAG, "测试数据EventHub"); }
/** * EventHub事件回调 */ callbackByEventHub = (content: string)=>{ promptAction.showToast({ message: JSON.stringify(content) }); }
private registerByEventHub = ()=>{ this.eventHub?.on(this.EVENT_TAG, this.callbackByEventHub); }
private unRegisterByEventHub = ()=>{ this.eventHub?.off(this.EVENT_TAG, this.callbackByEventHub); }
// --------------- Emitter private eventId: number = 1; private event: emitter.InnerEvent = { eventId: this.eventId, priority: emitter.EventPriority.LOW // 定义一个eventId为1的事件,事件优先级为Low };
private emitByEmitter(){ let eventData: emitter.EventData = { data: { content: '测试数据', id: 1, isEmpty: false } };
// 发送eventId为1的事件,事件内容为eventData emitter.emit(this.event, eventData); }
private callback = (eventData: emitter.EventData): void => { promptAction.showToast({ message: JSON.stringify(eventData) }); };
private registerByEmitter(){ emitter.on(this.event, this.callback); // 监听触发后,自动消除监听。不需要手动off emitter.once(this.event, this.callback) }
private unRegisterByEmitter(){ emitter.off(this.event.eventId, this.callback); }
// ---------------点击事件处理
onEmitEvent = ()=>{ this.emitByEmitter(); this.emitByEventHub(); }
onRegisterEvent = ()=>{ this.registerByEmitter(); this.registerByEventHub(); }
onUnRegisterEvent = ()=>{ this.unRegisterByEmitter(); this.unRegisterByEventHub();
} /** * 统一样式封装 */ @Styles ButtonStyle(){ .width(px2vp(350)) .height(px2vp(200)) .margin({ top: px2vp(66) }) }
build() { Column(){ Button("发送事件") .ButtonStyle() .onClick(this.onEmitEvent)
Button("监听事件") .ButtonStyle() .onClick(this.onRegisterEvent)
Button("取消事件") .ButtonStyle() .onClick(this.onUnRegisterEvent)
}.size({ width: "100%", height: "100%" }) }}
复制代码


发布于: 3 小时前阅读数: 7
用户头像

GeorgeGcs

关注

路漫漫其修远兮,吾将上下而求索。 2024-12-24 加入

历经腾讯,宝马,研究所,金融。 待过私企,外企,央企。 深耕大应用开发领域十年。 OpenHarmony,HarmonyOS,Flutter,H5,Android,IOS。 目前任职鸿蒙应用架构师。 HarmonyOS官方认证创作先锋

评论

发布
暂无评论
【HarmonyOS NEXT】EventHub和Emitter的使用场景与区别_HarmonyOS_GeorgeGcs_InfoQ写作社区