HarmonyOS 6.0 应用级事件总线与组件间通信
组件通信有Prop/Link、Provide/Consume、Watch这些正规军。但有些场景它们搞不定——跨Ability通信、非父子组件通信、一对多广播、解耦通信。这时候就得用事件总线。HarmonyOS提供了Emitter和CommonEvent两套方案分别管应用内和应用间但很多人分不清什么时候用哪个。通信方案对比方案通信范围耦合度适用场景Prop/Link父子组件高父子数据同步Provide/Consume跨层级中祖孙组件通信AppStorage全局中全局状态共享Emitter应用内任意低组件间解耦通信CommonEvent跨应用低系统事件、跨应用通知Emitter是应用内的事件总线CommonEvent是系统级的事件广播。大多数场景用Emitter就够了CommonEvent只在需要跟系统或其他应用通信时才用。Emitter基础Emitter是kit.BasicServicesKit提供的进程内事件机制import{emitter}fromkit.BasicServicesKit;// 定义事件IDconstEVENT_LOGIN_SUCCESS1001;constEVENT_CART_UPDATED1002;// 发送事件emitter.emit({eventId:EVENT_LOGIN_SUCCESS,parameters:{userId:12345,userName:张三}});// 接收事件emitter.on({eventId:EVENT_LOGIN_SUCCESS},(eventData:emitter.EventData){letparamseventData.parameters;letuserIdparams[userId]asstring;this.onLoginSuccess(userId);});eventId是数字类型的事件标识自己定义。parameters携带数据类型是Recordstring, Object。关键Emitter是进程内的同一个应用内才能收发。跨进程不同Ability运行在不同进程时Emitter不生效。Emitter取消订阅// 订阅时保存回调引用privateloginCallback(eventData:emitter.EventData){// 处理}aboutToAppear():void{emitter.on({eventId:EVENT_LOGIN_SUCCESS},this.loginCallback);}aboutToDisappear():void{emitter.off(EVENT_LOGIN_SUCCESS,this.loginCallback);}必须在aboutToDisappear中off取消订阅否则组件销毁后回调还在执行导致内存泄漏和空引用crash。off必须传跟on相同的回调函数引用。所以回调不能写成匿名函数要保存为类成员变量。一对多广播Emitter天然支持一对多——多个组件订阅同一个eventIdemit时所有订阅者都会收到// 购物车页面emitter.emit({eventId:EVENT_CART_UPDATED,parameters:{count:5}});// TabBar组件emitter.on({eventId:EVENT_CART_UPDATED},(data){this.cartBadgedata.parameters[count]asnumber;});// 首页组件emitter.on({eventId:EVENT_CART_UPDATED},(data){this.refreshRecommendations();});// 消息中心emitter.on({eventId:EVENT_CART_UPDATED},(data){this.checkPromotions();});三个组件同时监听购物车更新事件emit一次三个都收到。这是Prop/Link做不到的——它们需要组件有明确的层级关系。登录状态同步经典场景登录成功后多个页面需要更新状态constEVENT_USER_STATE_CHANGED2001;// 登录页asynclogin(username:string,password:string):Promisevoid{letuserawaitthis.authService.login(username,password);AppStorage.setOrCreate(currentUser,user);emitter.emit({eventId:EVENT_USER_STATE_CHANGED,parameters:{isLogin:true,userId:user.id}});}// 退出登录logout():void{this.authService.logout();AppStorage.delete(currentUser);emitter.emit({eventId:EVENT_USER_STATE_CHANGED,parameters:{isLogin:false}});}// 个人中心页aboutToAppear():void{emitter.on({eventId:EVENT_USER_STATE_CHANGED},this.onUserStateChanged);}privateonUserStateChanged(data:emitter.EventData){letisLogindata.parameters[isLogin]asboolean;if(isLogin){this.showUserInfo();}else{this.showLoginButton();}}为什么不直接用AppStorageAppStorage的数据变化会触发UI刷新但不会触发逻辑回调。比如退出登录时你不仅要更新UI还要清理缓存、取消请求、重置状态——这些是业务逻辑不是UI渲染。Emitter可以触发这些逻辑回调。封装事件总线直接用emitter的API有点啰嗦。封装一个类型安全的事件总线classEventBus{privatestaticinstance:EventBus;privatehandlers:Mapnumber,emitter.Callback[]newMap();staticgetInstance():EventBus{if(!EventBus.instance){EventBus.instancenewEventBus();}returnEventBus.instance;}on(eventId:number,callback:emitter.Callback):void{letexistingthis.handlers.get(eventId);if(existingundefined){existing[];}existing.push(callback);this.handlers.set(eventId,existing);emitter.on({eventId:eventId},callback);}off(eventId:number,callback:emitter.Callback):void{letexistingthis.handlers.get(eventId);if(existing!undefined){letnewList:emitter.Callback[][];for(leti0;iexisting.length;i){if(existing[i]!callback){newList.push(existing[i]);}}this.handlers.set(eventId,newList);}emitter.off(eventId,callback);}emit(eventId:number,parameters?:Recordstring,Object):void{if(parameters!undefined){emitter.emit({eventId:eventId,parameters:parameters});}else{emitter.emit({eventId:eventId});}}}封装后使用更简洁EventBus.getInstance().on(EVENT_LOGIN,this.onLogin);EventBus.getInstance().emit(EVENT_LOGIN,{userId:123});EventBus.getInstance().off(EVENT_LOGIN,this.onLogin);CommonEvent跨应用通信CommonEvent是系统级广播可以跨应用、跨进程import{commonEventManager}fromkit.BasicServicesKit;// 订阅系统事件letsubscribercommonEventManager.createSubscriber({events:[usual.event.SCREEN_OFF]});commonEventManager.subscribe(subscriber,(err,data){// 处理屏幕关闭事件});// 取消订阅commonEventManager.unsubscribe(subscriber);CommonEvent需要权限声明。很多系统事件需要对应权限才能订阅。自定义事件不需要权限但要确保事件名的唯一性——建议用包名作前缀letCUSTOM_EVENTcom.example.app.ORDER_CREATED;CommonEvent发送发送自定义CommonEventcommonEventManager.publish(com.example.app.ORDER_CREATED,{parameters:{orderId:20240101001,amount:99.9}},(err){if(!err){console.info(Event published);}});publish是异步的回调在发送完成后触发。注意CommonEvent的发送和接收可以在不同应用中。这意味着你的事件可能被其他应用监听到敏感数据不要直接放在parameters里。什么时候用CommonEventCommonEvent的使用场景很明确监听系统事件屏幕开关、网络变化、时区变化、电量变化跨应用通知支付应用通知订单完成地图应用接收导航请求多进程通信同一个应用的UIAbility和ExtensionAbility在不同进程应用内通信不要用CommonEvent——它比Emitter重得多涉及跨进程序列化而且有权限和可见性问题。时序控制事件到达顺序不保证。如果A事件必须在B事件之前处理constEVENT_STEP1_COMPLETE3001;// A完成后发事件emitter.emit({eventId:EVENT_STEP1_COMPLETE});// B等A完成才执行emitter.on({eventId:EVENT_STEP1_COMPLETE},(){this.executeStep2();});用事件链代替时序假设——A完成后emit通知B监听通知再执行。不要假设emit是同步的。内存泄漏防护Emitter的回调如果不off组件销毁后依然执行。最危险的情况// 危险匿名函数无法offemitter.on({eventId:1001},(data){this.updateUI();// 组件已销毁this可能无效});// 安全保存引用组件销毁时offprivatehandler(data:emitter.EventData){this.updateUI();}aboutToAppear():void{emitter.on({eventId:1001},this.handler);}aboutToDisappear():void{emitter.off(1001,this.handler);}规则on和off必须成对出现回调必须是类成员变量不能是匿名函数。踩坑清单问题原因解决组件销毁后crash没off取消订阅aboutToDisappear中offoff不掉匿名函数无法比较引用回调保存为类成员变量事件收不到Emitter跨进程不生效跨进程用CommonEvent收到重复事件多次on同一回调on前先off事件顺序不对emit不保证同步时序用事件链传递顺序CommonEvent收不到没声明权限检查module.json5权限自定义事件被拦截事件名不够唯一用包名作前缀参数类型丢失parameters反序列化只传基本类型数据敏感泄露CommonEvent跨应用可见敏感数据加密或用Emitter事件总线内存增长Map中回调越积越多off时清理Map记录事件总线是组件通信的后门——不用它时架构清晰用了它时调用链隐晦。能用Prop/Link解决的不要用Emitter能不跨进程的不要用CommonEvent。但当通信距离超出组件树范围时事件总线就是最干净的解法。

相关新闻

HarmonyOS 6.0 页面转场动画与共享元素进阶

HarmonyOS 6.0 页面转场动画与共享元素进阶

页面跳转时的动画不只是"好看"——它告诉用户"你从哪来,要到哪去"。没有动画的跳转像电视换台,突然蹦出一个新画面,用户要花半秒才能反应过来。好的转场动画是空间连续的,用户能感知到前后页面的逻辑关系。 N…

2026/7/27 14:05:26 阅读更多 →
【Django毕业设计】 基于 Django 的智能选课与退课审核系统轻量化校园学生选课排课管理系统(源码+文档+远程调试,全bao定制等)

【Django毕业设计】 基于 Django 的智能选课与退课审核系统轻量化校园学生选课排课管理系统(源码+文档+远程调试,全bao定制等)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

2026/7/27 14:05:26 阅读更多 →
rxjs-spy完全指南:从安装到高级调试的10个实用技巧

rxjs-spy完全指南:从安装到高级调试的10个实用技巧

rxjs-spy完全指南:从安装到高级调试的10个实用技巧 【免费下载链接】rxjs-spy A debugging library for RxJS 项目地址: https://gitcode.com/gh_mirrors/rx/rxjs-spy rxjs-spy是一款专为RxJS打造的调试库,它能帮助开发者轻松追踪、分析和调试RxJ…

2026/7/27 14:05:26 阅读更多 →

最新新闻

自考论文写作工具:智能选题与结构化写作指南

自考论文写作工具:智能选题与结构化写作指南

1. 项目概述"千笔专业论文写作工具"是一款面向自考学生的智能化写作辅助软件。作为在论文写作领域深耕多年的从业者,我见证了太多自考同学在论文写作过程中遇到的困境:从选题迷茫到资料收集困难,从格式混乱到查重不过关。这款工具正…

2026/7/28 2:08:28 阅读更多 →
5分钟快速上手Dify工作流:从零到一的AI自动化指南 [特殊字符]

5分钟快速上手Dify工作流:从零到一的AI自动化指南 [特殊字符]

5分钟快速上手Dify工作流:从零到一的AI自动化指南 🚀 【免费下载链接】Awesome-Dify-Workflow 分享一些好用的 Dify DSL 工作流程,自用、学习两相宜。 Sharing some Dify workflows. 项目地址: https://gitcode.com/GitHub_Trending/aw/Awe…

2026/7/28 2:08:28 阅读更多 →
全网稀缺资源验证:四步法确保信息可信度与合规使用

全网稀缺资源验证:四步法确保信息可信度与合规使用

1. 为什么这类“全网不多”的照片值得单独拿出来说 看到这个标题,你可能第一反应是:一张照片有什么好写的?但这类“全网不多”的资源,恰恰是很多人在实际工作中经常遇到的痛点——不是技术实现有多难,而是 资源稀缺性…

2026/7/28 2:08:28 阅读更多 →
PasteMD终极指南:一键解决AI内容到Office的格式转换难题

PasteMD终极指南:一键解决AI内容到Office的格式转换难题

PasteMD终极指南:一键解决AI内容到Office的格式转换难题 【免费下载链接】PasteMD 一键将 Markdown 和网页 AI 对话(ChatGPT/DeepSeek等)完美粘贴到 Word、WPS 和 Excel 的效率工具 | One-click paste Markdown and AI responses (ChatGPT/De…

2026/7/28 2:08:28 阅读更多 →
C/C++实现哥德巴赫猜想验证:从素数筛法到双指针算法优化

C/C++实现哥德巴赫猜想验证:从素数筛法到双指针算法优化

1. 项目概述:当经典数学猜想遇上C/C哥德巴赫猜想,这个困扰了数学界近三百年的难题,其表述却出奇地简洁:任何一个大于2的偶数都可以表示为两个素数之和。对于程序员,尤其是C/C开发者而言,这个猜想天然地散发…

2026/7/28 2:08:28 阅读更多 →
5分钟掌握Dify智能工作流:Awesome-Dify-Workflow终极自动化指南

5分钟掌握Dify智能工作流:Awesome-Dify-Workflow终极自动化指南

5分钟掌握Dify智能工作流:Awesome-Dify-Workflow终极自动化指南 【免费下载链接】Awesome-Dify-Workflow 分享一些好用的 Dify DSL 工作流程,自用、学习两相宜。 Sharing some Dify workflows. 项目地址: https://gitcode.com/GitHub_Trending/aw/Awes…

2026/7/28 2:07:27 阅读更多 →

日新闻

告别臃肿!3步让你的暗影精灵笔记本重获新生

告别臃肿!3步让你的暗影精灵笔记本重获新生

告别臃肿!3步让你的暗影精灵笔记本重获新生 【免费下载链接】OmenSuperHub Control Omen laptop performance, fan speeds, and keyboard lighting, and unlock power limits. 项目地址: https://gitcode.com/gh_mirrors/om/OmenSuperHub 你是否也曾为官方Om…

2026/7/28 0:00:43 阅读更多 →
RAG必踩坑!财报法规检索不准?这款开源工具让答案浮出水面,准确率飙升98.7%!

RAG必踩坑!财报法规检索不准?这款开源工具让答案浮出水面,准确率飙升98.7%!

做 RAG 的人应该都踩过这个致命的坑:把几百页的财报、法规、技术手册扔给向量库,问一个具体问题,搜出来的全是沾边但没用的内容 —— 关键信息要么被硬切块拆碎了,要么藏在几十条结果的最下面。语义相似≠真正相关,这个…

2026/7/28 0:00:43 阅读更多 →
抖音视频文案提取工具全指南:免费2026版、手机App、在线工具一网打尽

抖音视频文案提取工具全指南:免费2026版、手机App、在线工具一网打尽

2026年做短视频运营,从抖音上扒文案早就不是偷偷抄笔记的事了。我刚开始做内容的时候,每天刷半小时抖音,手动把爆款视频的口播敲进备忘录,一条2分钟的视频得花十来分钟,碰到语速快的还要反复回听。后来试了一圈工具&am…

2026/7/28 0:00:43 阅读更多 →

周新闻

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 数据集6000张 完整源码已标注数据集训练好的模型环境配置教程程序运行说明文档,可以直接使用!系统支持图片、视频、摄像头等多种方式检测裂缝,功能强大实用。 1数据集6000张 8各类别

2026/7/27 4:33:59 阅读更多 →
深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

pubg数据集 精选原图1.42万数据 1.49万标签 无任何重复、算法增强或冗余图像! pubg绝地求生目标检测数据集 1分类:e_body,14905个标签,txt格式 共计14244张图,99%为640*640尺寸图像 适合yolo目标检测、AI训练关键词&am…

2026/7/27 6:31:56 阅读更多 →
Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex检测数据集数据集详情检测类别: allies enemy tag图片总量:7247张训练集:5139张验证集:1425张测试集:683张标注状态:全部已标注,即拿即用数据格式:支持YOLO格式及其他格式&#…

2026/7/27 4:01:12 阅读更多 →

月新闻