Harmony中EventHub实现发布订阅

目录:

1. EventHub 核心概念

  • 发布者(Publisher):触发事件的模块(如登录模块)。
  • 订阅者(Subscriber):监听事件的模块(如购物车、个人中心)。
  • 事件(Event):携带数据的消息对象,通过唯一eventId标识。

2. 案例场景

  • 功能需求: 用户登录成功后,购物车模块和个人中心模块需实时更新UI(如显示用户名、刷新数据)。
  • 传统问题: 若直接调用购物车/个人中心的方法,会导致模块间强耦合。
  • EventHub解决方案: 登录模块发布"登录成功"事件,其他模块订阅该事件并自主响应。

3. 代码实现步骤

步骤1:定义事件类型

在公共层(Common)中定义事件ID和数据类型:

typescript 复制代码
// common/src/main/ets/event/EventTypes.ets
export const EVENT_USER_LOGIN = 'user_login'; // 事件ID

export interface LoginEventData {
  userId: string;
  userName: string;
}

步骤2:发布事件(登录模块)

登录成功后,通过EventHub发布事件:

typescript 复制代码
// features/login/src/main/ets/LoginService.ets
import { EventHub } from '@ohos/baseEvent';
import { EVENT_USER_LOGIN, LoginEventData } from '@common/event/EventTypes';

function handleLoginSuccess(userId: string, userName: string) {
  // 1. 本地处理登录逻辑
  // ... 

  // 2. 发布事件
  const eventData: LoginEventData = { userId, userName };
  EventHub.emit(EVENT_USER_LOGIN, eventData); // 关键发布动作
}

步骤3:订阅事件(购物车模块)

购物车模块初始化时订阅事件:

typescript 复制代码
// features/cart/src/main/ets/CartPage.ets
import { EventHub } from '@ohos/baseEvent';
import { EVENT_USER_LOGIN, LoginEventData } from '@common/event/EventTypes';

@Entry
@Component
struct CartPage {
  @State userName: string = '未登录';

  aboutToAppear() {
    // 订阅事件
    EventHub.on(EVENT_USER_LOGIN, (data: LoginEventData) => {
      this.userName = data.userName; // 更新UI
      this.refreshCartData(data.userId); // 刷新购物车数据
    });
  }

  // 取消订阅(避免内存泄漏)
  aboutToDisappear() {
    EventHub.off(EVENT_USER_LOGIN);
  }

  build() {
    Column() {
      Text(`用户: ${this.userName}`).fontSize(20)
      // 购物车列表...
    }
  }
}

步骤4:订阅事件(个人中心模块)

同理,个人中心模块订阅同一事件:

typescript 复制代码
// features/profile/src/main/ets/ProfilePage.ets
import { EventHub } from '@ohos/baseEvent';
import { EVENT_USER_LOGIN } from '@common/event/EventTypes';

@Entry
@Component
struct ProfilePage {
  @State userName: string = '未登录';

  aboutToAppear() {
    EventHub.on(EVENT_USER_LOGIN, (data: LoginEventData) => {
      this.userName = data.userName;
      this.loadUserProfile(data.userId);
    });
  }

  aboutToDisappear() {
    EventHub.off(EVENT_USER_LOGIN);
  }
}

4. EventHub 的底层实现(可选扩展)

若需自定义EventHub,可在Common层实现:

typescript 复制代码
// common/src/main/ets/utils/EventHub.ets
type Callback<T> = (data: T) => void;

class EventHub {
  private static events: Map<string, Callback<any>[]> = new Map();

  // 订阅事件
  static on<T>(eventId: string, callback: Callback<T>) {
    if (!this.events.has(eventId)) {
      this.events.set(eventId, []);
    }
    this.events.get(eventId)?.push(callback);
  }

  // 发布事件
  static emit<T>(eventId: string, data: T) {
    const callbacks = this.events.get(eventId);
    callbacks?.forEach(cb => cb(data));
  }

  // 取消订阅
  static off(eventId: string) {
    this.events.delete(eventId);
  }
}

export default EventHub;

5. 关键注意事项

6. 完整流程图示

通过EventHub的发布-订阅模式,登录模块无需知道购物车和个人中心的存在,只需发布事件,订阅方自主响应,实现彻底解耦。此模式特别适合鸿蒙的原子化服务场景,支持动态部署的Feature独立通信。

相关推荐
天才奇男子6 分钟前
HAProxy高级功能全解析
linux·运维·服务器·微服务·云原生
小李独爱秋22 分钟前
“bootmgr is compressed”错误:根源、笔记本与台式机差异化解决方案深度指南
运维·stm32·单片机·嵌入式硬件·文件系统·电脑故障
学嵌入式的小杨同学25 分钟前
【Linux 封神之路】信号编程全解析:从信号基础到 MP3 播放器实战(含核心 API 与避坑指南)
java·linux·c语言·开发语言·vscode·vim·ux
酥暮沐1 小时前
iscsi部署网络存储
linux·网络·存储·iscsi
❀͜͡傀儡师1 小时前
centos 7部署dns服务器
linux·服务器·centos·dns
Dying.Light2 小时前
Linux部署问题
linux·运维·服务器
S19012 小时前
Linux的常用指令
linux·运维·服务器
萤丰信息2 小时前
AI 筑基・生态共荣:智慧园区的价值重构与未来新途
大数据·运维·人工智能·科技·智慧城市·智慧园区
小义_2 小时前
【RH134知识点问答题】第7章 管理基本存储
linux·运维·服务器
运维小欣2 小时前
Agentic AI 与 Agentic Ops 驱动,智能运维迈向新高度
运维·人工智能