loveinter2003 发表于 2025-4-3 15:12:20

HarmonyOSNEXT—应用通信之Emitter

HarmonyOSNEXT—应用通信之Emitter

序言

在应用开发过程中,我们对于应用中数据和响应事件的传递,都会选择不同的通信方式,在选择这些通信方式时,我们需要考虑不同通信方式下我们的实现逻辑,以及是否满足我们的需求,本文主要介绍,应用在同一进程的通信方式
一、基于同进程的通信方式——Emitter

简介:

Emitter提供在同一进程不同线程,或者同一进程同一线程的通信方式,在应用开发中通常被用作组件间,或者窗口间传递消息;注意如果跨线程传递数据,数据是会被自动序列化的
使用方式:

    // 单次订阅,收到回调后,自动取消订阅
    emitter.once({eventId: 1}, () => {
      console.info('once callback');
    });
    emitter.once("onceClick", () => {
      console.info('once onClick callback');
    });    // 持续订阅事件,没有取消订阅就会一直接收消息
    emitter.on({eventId: 2}, () => {
      console.info('once callback');
    });
    emitter.on("Click", () => {
      console.info('on onClick callback');
    });    let eventData: emitter.EventData = {
      data: {
      "once": "send",
      }
    };
    // 发送指定事件
    emitter.emit({eventId: 1}, eventData)
    emitter.emit("onceClick" , eventData)
    emitter.emit("onceClick" ,{ priority: emitter.EventPriority.HIGH }, eventData)    // 取消事件的订阅
    emitter.off(2)
    emitter.off("Click")
    // 取消指定回调的事件订阅
    emitter.off(1, callback)
    emitter.off("onceClick", callback)二、项目示例:

使用Emitter来完成跨窗口传递消息,并在指定页面进行刷新,主要用于在同一进程下,不同的窗口或者不同上下文间传递消息
// index.ets
import { emitter } from '@kit.BasicServicesKit';
import { MyWindowManager } from '../util/windowManger';

@Entry
@Component
struct Index {
@State message: string = 'Hello World';

aboutToAppear(): void {
    emitter.on('click', (data) => {
      let result = data.data
      this.message = result?.TestEmitter
      MyWindowManager.getInstance().closeDialog("testEmitterDialog")
    })
}

build() {
    Column({space: 20}) {
      Text(this.message).fontSize(50).fontWeight(FontWeight.Bold).margin({top: 50})
      Button("第一个弹框")
      .fontSize(50)
      .fontWeight(FontWeight.Bold)
      .onClick(() => {
          MyWindowManager.getInstance().showDialogView("testEmitterDialog", 0)
      })
    }
    .height('100%')
    .width('100%')
}
}

// TestEmitter.ets
import { emitter } from '@kit.BasicServicesKit';

@Entry
@Component
struct TestEmitter {
@State message: string = 'TestEmitter';

build() {
    Column({space: 20}) {
      Text("这是一个弹框").fontSize(50)
      .fontWeight(FontWeight.Bold)
      Button("点击弹框发送消息")
      .fontSize(26)
      .fontWeight(FontWeight.Bold)
      .onClick(() => {
          emitter.emit('click', {
            data: {
            "TestEmitter": this.message
            }
          })
      })
    }
    .height('100%')
    .width('100%')
}
}

// windowManger.ets
import window from '@ohos.window';
import { display } from '@kit.ArkUI';

const TAG = "WindowManager"
export class MyWindowManager {

static getInstance(): MyWindowManager {
    if (globalThis.mWindowManager == null) {
      globalThis.mWindowManager = new MyWindowManager();
    }
    return globalThis.mWindowManager;
}

showDialogView(dialogName: string, offsetY: number) {
    console.log(TAG, "showDialogView")
    let dialogView = AppStorage.get(dialogName) as window.Window;
    if (dialogView) {
      console.log(TAG, "dialogViewshowWindow")
      dialogView.showWindow(() => {
      dialogView.setWindowFocusable(true);
      dialogView.setWindowTouchable(true);
      });
    } else {
      console.log(TAG, "dialogView is undefined ");
      this.createDialogWindow(dialogName, offsetY);
    }
}

closeDialog(dialogName: string) {
    try {
      let dialogView = AppStorage.get(dialogName) as window.Window
      if (!dialogView) {
      console.log(TAG, "dialogView is null")
      }
      dialogView.destroyWindow()
      AppStorage.set(dialogName, null)
    } catch (e) {
      console.error(TAG, 'close window err' + JSON.stringify(e))
    }
}

/**
   * 创建Dialog提示窗口
   */
async createDialogWindow(dialogName: string, offsetY: number) {
    try {
      let config: window.Configuration = {
      ctx: globalThis.context,
      name: dialogName,
      windowType: window.WindowType.TYPE_DIALOG
      }
      let win = await window.createWindow(config)
      await win.setPreferredOrientation(window.Orientation.UNSPECIFIED);
      await win.setUIContent('pages/' + "TestEmitter")
      let dis = display.getDefaultDisplaySync()
      console.log(TAG, "dis.height: " + dis.height)
      await win.resize(dis.width -100, 300)
      await win.moveWindowTo(50, dis.height - vp2px(300) - vp2px(offsetY))
      await win.showWindow()
      win.setWindowBackgroundColor('#33000000')
      win.setWindowFocusable(true)
      win.setWindowTouchable(true)
      AppStorage.setOrCreate(dialogName, win)
    } catch (e) {
      console.error(TAG, 'createDialogWindow err = ' + JSON.stringify(e))
    }
}
}
页: [1]
查看完整版本: HarmonyOSNEXT—应用通信之Emitter