当前位置: 首页 > news >正文

HarmonyOS 事件管理进阶:on / off 精准控制回调的正确姿势

文章目录前言on vs onSubscribe两者有什么区别精准取消off(eventId, callback)once单次订阅的原始版getListenerCount订阅数统计排查泄漏神器完整生命周期管理示例一个容易踩的坑重复订阅写在最后前言近期发现一款很有意思的HarmonyOS 三方库, 地址 pura/harmony-utils(V1.4.0) , 作者是桃花镇童长老, 我这里也是直接通过该作者公布的源码进行案例编写进行,写了到目前写了一部分demo ,感觉确实很有帮助,这里呢也是开始写一个系列的演示demo 供大家参考。如有帮助可以在OpenHarmony中进行下载安装进行使用哦案例demo导航展示↓↓↓↓↓↓接下来言归正传 ↓↓↓↓上篇讲了onSubscribe和post的基本用法。这篇聊个更精细的话题怎么精准控制哪个回调被取消以及怎么监控当前的订阅数量。这在实际项目里很有用。想象一下同一个事件你注册了两个回调A 用来更新 UIB 用来记录日志。某个时刻你只想停掉 BA 继续运行——这时候unSubscribe就不够用了它会把所有回调都干掉。on vs onSubscribe两者有什么区别先搞清楚这对兄弟的区别。onSubscribe是封装版回调直接接收解包后的数据EmitterUtil.onSubscribestring(EVT_NORMAL,(msg){// msg 就是字符串直接用this.addLog([onSubscribe] →${msg});});on是原始版回调接收的是GenericEventData对象需要自己取data.dataEmitterUtil.onstring(EVT_TYPED,this.namedCallback);对应的回调定义是这样的privatenamedCallback:Callbackemitter.GenericEventDatastring(data){this.addLog([on精准] 收到:${data.data});};on的核心优势是你保存了回调函数的引用就可以在之后精准取消它。精准取消off(eventId, callback)演示页里专门有两个按钮来展示精准取消和全量取消的区别// 精准取消只取消 namedCallback 这一个回调EmitterUtil.offstring(EVT_TYPED,this.namedCallback);this.addLog([off精准] namedCallback 已取消);this.refreshCount();// 全量取消取消 EVT_TYPED 下所有回调EmitterUtil.offstring(EVT_TYPED);this.addLog([off全量] EVT_TYPED 所有订阅已取消);this.refreshCount();两者的区别off(eventId, callback)只取消指定的那个回调其他回调继续存活off(eventId)取消该事件下的所有回调精准取消的前提是你必须保存回调函数的引用。这就是为什么演示代码里要把回调定义为 class 的成员属性// 保存引用才能精准取消privatenamedCallback:Callbackemitter.GenericEventDatastring(data){this.addLog([on精准] 收到:${data.data});};如果写成匿名函数// ❌ 这样写无法精准取消每次都是新的函数对象EmitterUtil.onstring(EVT_TYPED,(data){this.addLog(data.data??);});匿名函数每次执行都会创建新的函数对象你没法拿到之前那个引用所以没办法精准取消。once单次订阅的原始版和onceSubscribe对应once是单次订阅的原始版同样接收GenericEventData// once 重新单次订阅EmitterUtil.oncestring(EVT_ONCE,(data){this.addLog([once重订] 收到:${data.data});});this.addLog([once] 已重新注册单次订阅);this.refreshCount();使用场景当你的onceSubscribe已经触发过自动取消了但你又需要再监听一次下一个事件时就可以用once手动重新注册。getListenerCount订阅数统计排查泄漏神器这个 API 很容易被忽略但在调试和排查内存问题时非常有用。refreshCount(){constnEmitterUtil.getListenerCount(EVT_NORMAL);constoEmitterUtil.getListenerCount(EVT_ONCE);consttEmitterUtil.getListenerCount(EVT_TYPED);this.listenerCountnot;this.addLog([getListenerCount] normal:${n}once:${o}typed:${t});}getListenerCount返回指定事件当前的订阅者数量。什么时候用它调试阶段确认订阅有没有正确注册数量是不是你预期的排查泄漏如果你发现某个事件的订阅数一直在增长说明某处订阅没有被取消动态控制在注册新订阅前先检查是否已经订阅过避免重复注册演示页在每次操作后都刷新订阅数显示StatelistenerCount:number0;// 顶部显示当前总订阅数Text(当前总订阅数this.listenerCount).fontSize(14).fontColor(#555)你可以通过观察这个数字的变化直观感受每次on/off操作对订阅数的影响。完整生命周期管理示例把on、off和getListenerCount结合起来一个完整的生命周期管理长这样EntryComponentstruct EmitterUtilDemoPage{Statelogs:MsgItem[][];StatelistenerCount:number0;privatenamedCallback:Callbackemitter.GenericEventDatastring(data){this.addLog([on精准] 收到:${data.data});};aboutToAppear(){// 注册时统计EmitterUtil.onstring(EVT_TYPED,this.namedCallback);this.refreshCount();}aboutToDisappear(){// 销毁时清理EmitterUtil.offstring(EVT_TYPED);}refreshCount(){constnEmitterUtil.getListenerCount(EVT_NORMAL);constoEmitterUtil.getListenerCount(EVT_ONCE);consttEmitterUtil.getListenerCount(EVT_TYPED);this.listenerCountnot;this.addLog([getListenerCount] normal:${n}once:${o}typed:${t});}}一个容易踩的坑重复订阅如果你在aboutToAppear里注册了订阅但页面因为某些原因被反复创建销毁每次创建都会注册一个新的回调。如果销毁时没有清理订阅数会一直累积。用getListenerCount可以快速验证这个问题。如果发现数量比预期大就去查对应的注册/取消逻辑。写在最后精准控制订阅的关键点就两个保存回调引用用 class 成员属性存回调不要用匿名函数配对管理注册和取消成对出现aboutToAppear和aboutToDisappear对应getListenerCount是一个非常好的调试工具建议在开发阶段多用能帮你提前发现潜在的内存泄漏问题。
http://www.rkmt.cn/news/1406293.html

相关文章:

  • 物流回单自动识别和关联订单的技术方案是怎样的?2026AI Agent实战指南
  • MTL 8750-CA-NS控制器模块
  • 从《水果忍者》到你的游戏:Unity刀痕效果实战避坑指南(TrailRenderer vs LineRenderer)
  • 探索抖音内容获取的艺术:从手动保存到智能采集的进化之路
  • 保姆级教程:QGC地面站二次开发中,如何为你的无人机配置TCP、串口和UDP通信(附实战避坑点)
  • Qt Creator版本太多搞晕了?保姆级指南教你为不同Qt版本(5.14.2 / 6.2.4)匹配正确的ros_qtc_plugin插件
  • 对比直接购买与通过Taotoken使用大模型API的优劣
  • 智芯车规MCU开发踩坑记:Keil添加芯片包、JLink识别不到设备的那些坑,我都帮你填平了
  • 混合线性与稀疏性鲁棒自编码器:原理、实现与调参指南
  • 揭秘AI Agent:企业部署后哪些核心环节能实现降本增效快速见效?
  • c#基础6
  • 告别重复输入密码!用Linux expect脚本批量管理服务器,5分钟搞定自动化登录
  • Simulink FFT分析:从模型搭建到谐波解读实战指南
  • 【数据校验实战】用 AI 对比源数据库与目标数仓的数据一致性脚本编写
  • 阻抗匹配介绍
  • SAP-ABAP:条件判断与循环控制语句(7篇) 第二篇:进阶实战:多重条件嵌套与switch语句的选型对比
  • 【ChatGPT旅行规划辅助实战指南】:20年IT架构师亲测的7大避坑法则与实时行程优化公式
  • ChatGPT面试准备终极清单:1份Prompt=1次高保真模拟+1份弱点雷达图+1条升职级话术
  • Maven命令
  • 知乎盐选专栏作者都在偷偷用的ChatGPT提示工程:12个领域专属指令集(含法律/医学/职场类防翻车模板)
  • SpringBoot项目里,用SpringSecurity+JWT做权限控制,我踩过的那些坑都帮你填好了
  • 如何用AI短视频创作工具3分钟完成专业视频制作:Pixelle-Video完全指南
  • 别再只下载现成的了!手把手教你用Ollama+llama.cpp打造专属中文大模型(以Chinese-Mistral-7B为例)
  • 规则歧义全拆解,深度还原ChatGPT如何将“每轮限抽2张牌”误译为“永久弃牌”的底层token解析逻辑
  • ChatGPT旅行规划辅助:3步生成合规签证文案+动态预算追踪表(附可运行Prompt模板)
  • 鸣潮自动化助手:5分钟解放双手,告别重复刷本的终极方案
  • 【限时公开】头部音乐厂牌内部使用的ChatGPT歌词增强协议(含版权合规校验模块)
  • 不止于备份:用群晖NFS+CentOS 7.9搭建轻量级开发测试环境共享存储
  • COM3D2 MaidFiddler:打造你的专属女仆管家,实时编辑让游戏体验更自由
  • 为AI智能体构建本地持久化记忆:VEKTOR实战指南