场景描述

在HarmonyOS开发中,事件通信是一种重要的通信手段,它支持同Ability、跨Ability、跨线程以及跨进程通信。当前提供的通信方式主要有Emitter、EventHub、CommonEvent,线程间通信也可以使用Worker和Taskpool提供的postMessage和sendData向数组线程发送消息。应用间通信可以使用自定义公共事件和IPC&RPC两种方式。

能力支持

  • 同Ability通信:Emitter、EventHub、CommonEvent
  • 跨Ability通信:Emitter、EventHub、CommonEvent
  • 跨线程通信:Emitter、CommonEvent、Worker、Taskpool
  • 跨进程通信:CommonEvent、IPC&RPC
方案描述
场景一:同Ability通信

通过Eventhub订阅事件打开自定义弹窗:

private uiAbilityContext = getContext() as common.UIAbilityContext;

aboutToAppear(): void {
  this.uiAbilityContext.eventHub.on('openDialog', () => {
    this.openDialog('自定义弹窗');
  });
}

openDialog(str: string) {
  let uiContext = this.getUIContext();
  let promptAction = uiContext.getPromptAction();
  let contentNode = new ComponentContent(uiContext, wrapBuilder(buildText), new Params(str));
  promptAction.openCustomDialog(contentNode);
}

this.uiAbilityContext.eventHub.emit('openDialog');

this.uiAbilityContext.eventHub.off('openDialog');
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.

HarmonyOS开发之事件通信_事件通信

场景二:跨Ability通信

使用EventHub进行数据通信:

private applicationContext = getContext().getApplicationContext();

eventFunc(arg: Dog) {
  promptAction.showDialog({
    'message': 'dog age is ' + arg.age
  });
}

aboutToAppear(): void {
  this.applicationContext.eventHub.on('myEvent', this.eventFunc);
}

@Observed
class Dog {
  public age: number;

  constructor(age: number) {
    this.age = age;
  }
}

this.applicationContext.eventHub.emit("myEvent", this.dog);

this.applicationContext.eventHub.off('myEvent');
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
场景三:线程间通信

使用Worker线程执行字符串倒序:

async executeWorkerFunc(inPutStr: string) {
  if (!inPutStr.length) {
    this.jsWorkerOutPutStr = "No input for the string to be reserved.\n";
    return;
  }
  this.myWorker.postMessage(inPutStr);
  let strFlag = false;
  let outPutStr = '';
  this.myWorker.onmessage = (e) => {
    outPutStr = e.data.toString();
    strFlag = true;
  }
  this.jsWorkerOutPutStr = outPutStr;
}

// worker.ets
let workerPort: ThreadWorkerGlobalScope = worker.workerPort;

workerPort.onmessage = (e: MessageEvents) => {
  let oldData : string = e.data;
  let newData = oldData.split("").reverse().join("");
  workerPort.postMessage(newData);
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.

使用taskpool实现字符串排序:

emitter.on("eventId", (eventData: emitter.EventData) => {
  promptAction.showToast({
    message: 'receive' + eventData.data?.content,
    duration: 2000
  });
});

async executeImmediately() {
  if (!this.taskPoolInPutStr.length) {
    this.taskPoolOutPutStr = 'No input for the string to be sorted.\n';
    return;
  }
  let task = new taskpool.Task(strSort, this.taskPoolInPutArr);
  this.taskPoolStack.push(task);
  await taskpool.execute(task).then((result) => {
    this.taskPoolOutPutStr = `${this.taskPoolOutPutStr}Task executed successfully: ${result.toString()}`;
  }).catch((e: Error) => {
    this.taskPoolOutPutStr += `Task executed failed:${e.toString()}`;
  });
  this.taskPoolStack.pop();
}

function strSort(inPutArr: string[]): string[] {
  let newArr = inPutArr.sort();
  let eventData: emitter.EventData = {
    data: {
      'content': JSON.stringify(newArr),
    }
  };
  emitter.emit('eventId', eventData);
  return newArr;
}
  • 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.
场景四:进程间通信

使用CommonEvent自定义公共事件:

// 发布方
let options: CommonEventManager.CommonEventPublishData = {
  bundleName: 'com.example.mysubscriber',
};
CommonEventManager.publish('eventTest', options, (err: Base.BusinessError) => {
  if (err) {
    hilog.error(0xFF00, LOG_TAG, `PublishCallBack err = ${JSON.stringify(err)}`);
  } else {
    hilog.info(0xFF00, LOG_TAG, 'commonEvent Publish success');
  }
});

// 订阅方
let subscriber: CommonEventManager.CommonEventSubscriber;
let subscribeInfo: CommonEventManager.CommonEventSubscribeInfo = {
  events: ['eventTest'],
};

function SubscribeCB(err: Base.BusinessError, data: CommonEventManager.CommonEventData) {
  if (err) {
    hilog.error(0xFF00, LOG_TAG, `subscribe failed, code is ${err.code}, message is ${err.message}`);
  } else {
    publishNotification();
    hilog.info(0xFF00, LOG_TAG, 'subscribe success');
  }
}

function createCB(err: Base.BusinessError, commonEventSubscriber: CommonEventManager.CommonEventSubscriber) {
  if (!err) {
    hilog.info(0xFF00, LOG_TAG, 'createSubscriber');
    subscriber = commonEventSubscriber;
    CommonEventManager.subscribe(subscriber, SubscribeCB);
  } else {
    hilog.error(0xFF00, LOG_TAG, `createSubscriber failed, code is ${err.code}, message is ${err.message}`);
  }
}

async function publishNotification() {
  let wantAgent: _WantAgent;
  let wantAgentInfo: WantAgent.WantAgentInfo = {
    wants: [
      {
        bundleName: 'com.example.mysubscriber',
        abilityName: 'EntryAbility',
      } as Want
    ],
    operationType: WantAgent.OperationType.START_ABILITIES,
    requestCode: 0,
    wantAgentFlags: [WantAgent.WantAgentFlags.UPDATE_PRESENT_FLAG]
  };

  WantAgent.getWantAgent(wantAgentInfo).then((data) => {
    wantAgent = data;
    let notificationRequest: notificationManager.NotificationRequest = {
      content: {
        notificationContentType: notificationManager.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT,
        normal: {
          title: '自定义公共事件',
          text: '收到其他应用一条消息',
          additionalText: 'Test_AdditionalText',
        },
      },
      id: 6,
      tapDismissed: true,
      notificationSlotType: notificationManager.SlotType.SOCIAL_COMMUNICATION,
      label: 'Receive CommonEvent',
      wantAgent: wantAgent,
    };
    notificationManager.publish(notificationRequest);
  });
}
  • 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.

其它常见问题

  1. 粘性事件:HarmonyOS的Emitter不支持粘性事件,可以考虑使用自定义公共事件实现。
  2. 事件处理优先级:可以使用emitter定义事件优先级为idle,以确保低优先级任务不会阻塞主线程。