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

George_wu_
发布于 2025-3-26 23:09
浏览
1收藏

一、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.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  1. 在page界面或者组件中,通过UIcontext强转为UIAbilityContext获取:
let context = getContext(this) as common.UIAbilityContext;
let eventhub = context.eventHub;
  • 1.
  • 2.

获得到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下的所有注册回调都清空
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.

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

二、Emitter是什么?

【HarmonyOS NEXT】EventHub和Emitter的使用场景与区别-鸿蒙开发者社区

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

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

  private event: emitter.InnerEvent = {
    eventId: this.eventId,
    priority: emitter.EventPriority.LOW   // 定义一个eventId为1的事件,事件优先级为Low
  };
  • 1.
  • 2.
  • 3.
  • 4.

事件级别分为以下几种类型:
【HarmonyOS NEXT】EventHub和Emitter的使用场景与区别-鸿蒙开发者社区
和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
      }
    };
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.

事件的广播发送,订阅和取消订阅与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);
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.

详情参见官网,示例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
@Component
struct 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%"
    })
  }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.
  • 101.
  • 102.
  • 103.
  • 104.
  • 105.
  • 106.
  • 107.
  • 108.
  • 109.
  • 110.
  • 111.
  • 112.
  • 113.
  • 114.
  • 115.
  • 116.
  • 117.
  • 118.

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
收藏 1
回复
举报
1


回复
    相关推荐