[开发者活动] HarmonyOSNEXT—应用通信之Emitter

ouyangzhi 显示全部楼层 发表于 2025-3-27 12:31:35

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, "dialogView  showWindow")
      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))
    }
  }
}

©著作权归作者所有,转载或内容合作请联系作者

您尚未登录,无法参与评论,登录后可以:
参与开源共建问题交流
认同或收藏高质量问答
获取积分成为开源共建先驱

Copyright   ©2025  OpenHarmony开发者论坛  京ICP备2020036654号-3 |技术支持 Discuz!

返回顶部