场景描述
在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');
场景二:跨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');
场景三:线程间通信
使用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);
}
使用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;
}
场景四:进程间通信
使用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);
});
}
其它常见问题
- 粘性事件:HarmonyOS的Emitter不支持粘性事件,可以考虑使用自定义公共事件实现。
- 事件处理优先级:可以使用emitter定义事件优先级为idle,以确保低优先级任务不会阻塞主线程。