EventBus的使用与跨页面通信指南

数据由AI生成。

一、EventBus简介

在鸿蒙ArkUI开发中,EventBus是一种基于发布/订阅模式的通信机制,允许不同组件或页面之间进行解耦通信。系统自带的EventBus功能在API12+中得到了增强。

二、基本使用

1. 创建EventBus实例

import emitter from '@ohos.events.emitter';

// 创建内部事件
const event: emitter.InnerEvent = {
  eventId: 1 // 事件ID
};

// 创建事件数据
const eventData: emitter.EventData = {
  data: {
    "key": "value" // 需要传递的数据
  }
};

2. 发送事件

// 发送事件
emitter.emit(event, eventData);

3. 订阅事件

// 创建订阅信息
const subscribeInfo: emitter.SubscribeInfo = {
  eventId: 1, // 订阅的事件ID
  priority: emitter.EventPriority.HIGH // 事件优先级
};

// 订阅事件回调
emitter.on(subscribeInfo, (eventData: emitter.EventData) => {
  console.info("收到事件数据: " + JSON.stringify(eventData.data));
});

4. 取消订阅

emitter.off(subscribeInfo.eventId);

三、跨页面通信实现

1. 页面A发送事件

// PageA.ets
import emitter from '@ohos.events.emitter';

@Entry
@Component
struct PageA {
  build() {
    Column() {
      Button('发送事件到PageB')
        .onClick(() => {
          const event: emitter.InnerEvent = {
            eventId: 1001
          };
          const eventData: emitter.EventData = {
            data: {
              "message": "Hello from PageA"
            }
          };
          emitter.emit(event, eventData);
        })
    }
  }
}

2. 页面B接收事件

// PageB.ets
import emitter from '@ohos.events.emitter';

@Entry
@Component
struct PageB {
  @State message: string = '等待消息...';
  
  aboutToAppear() {
    // 订阅事件
    const subscribeInfo: emitter.SubscribeInfo = {
      eventId: 1001,
      priority: emitter.EventPriority.HIGH
    };
    
    emitter.on(subscribeInfo, (eventData: emitter.EventData) => {
      this.message = eventData.data['message'];
    });
  }
  
  aboutToDisappear() {
    // 取消订阅
    emitter.off(1001);
  }
  
  build() {
    Column() {
      Text(this.message)
        .fontSize(20)
    }
  }
}

四、异步转同步实现

1. 使用Promise封装

// EventBusUtil.ets
import emitter from '@ohos.events.emitter';

export class EventBusUtil {
  private static responseMap: Map<number, (data: any) => void> = new Map();
  private static requestId: number = 0;

  // 发送请求并等待响应
  static async sendRequest(eventId: number, requestData: any): Promise<any> {
    return new Promise((resolve) => {
      const currentRequestId = ++this.requestId;
      
      // 订阅响应事件
      const responseEventId = eventId + 10000; // 响应事件ID约定
      const subscribeInfo: emitter.SubscribeInfo = {
        eventId: responseEventId,
        priority: emitter.EventPriority.HIGH
      };
      
      this.responseMap.set(currentRequestId, resolve);
      
      emitter.once(subscribeInfo, (eventData: emitter.EventData) => {
        const handler = this.responseMap.get(currentRequestId);
        if (handler) {
          handler(eventData.data);
          this.responseMap.delete(currentRequestId);
        }
      });
      
      // 发送请求
      const event: emitter.InnerEvent = {
        eventId: eventId
      };
      const eventData: emitter.EventData = {
        data: {
          ...requestData,
          requestId: currentRequestId
        }
      };
      emitter.emit(event, eventData);
    });
  }

  // 处理请求并发送响应
  static handleRequest(eventId: number, callback: (data: any) => any) {
    const subscribeInfo: emitter.SubscribeInfo = {
      eventId: eventId,
      priority: emitter.EventPriority.HIGH
    };
    
    emitter.on(subscribeInfo, async (eventData: emitter.EventData) => {
      const requestData = eventData.data;
      const result = await callback(requestData);
      
      // 发送响应
      const responseEventId = eventId + 10000;
      const responseEvent: emitter.InnerEvent = {
        eventId: responseEventId
      };
      const responseEventData: emitter.EventData = {
        data: {
          ...result,
          requestId: requestData.requestId
        }
      };
      emitter.emit(responseEvent, responseEventData);
    });
  }
}

2. 使用示例

请求方:

// 在某个页面或组件中
async function fetchData() {
  try {
    const result = await EventBusUtil.sendRequest(2001, { 
      param1: 'value1',
      param2: 'value2'
    });
    console.info('收到响应:', result);
  } catch (error) {
    console.error('请求失败:', error);
  }
}

响应方:

// 在应用初始化或服务中
EventBusUtil.handleRequest(2001, async (requestData) => {
  console.info('收到请求:', requestData);
  // 处理请求...
  return {
    status: 'success',
    data: '处理后的数据'
  };
});

五、高级特性

1. 一次性订阅

// 使用emitter.once替代emitter.on
emitter.once(subscribeInfo, (eventData: emitter.EventData) => {
  // 这个回调只会执行一次
});

2. 事件优先级

// 订阅时可以设置优先级
const highPrioritySubscribeInfo: emitter.SubscribeInfo = {
  eventId: 1,
  priority: emitter.EventPriority.HIGH // 可选HIGH, DEFAULT, LOW
};

3. 带权限的事件

// 发送带权限的事件
const restrictedEvent: emitter.InnerEvent = {
  eventId: 1,
  permissions: ["permission1", "permission2"] // 需要声明相应权限
};

六、注意事项

  1. 事件ID需要在全局统一管理,避免冲突

  2. 及时取消不再需要的事件订阅,防止内存泄漏

  3. 跨页面通信时注意页面生命周期,在aboutToDisappear中取消订阅

  4. 大数据传输考虑使用其他机制,EventBus适合小数据量通信

  5. 在UI线程中处理事件时避免耗时操作