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

HarmonyOS事件订阅与通知:后台事件处理

本文将深入探讨HarmonyOS 5(API 12)中的事件订阅与通知机制,重点讲解如何在后台处理事件,实现应用的实时响应和跨设备协同。内容涵盖核心API、实现步骤、实战示例及性能优化建议。

1. 事件订阅与通知机制概述

HarmonyOS的事件系统采用发布-订阅模式,允许应用在后台监听和处理系统事件、自定义事件及跨设备事件。其核心优势包括:

  • 跨进程通信:支持应用间事件传递,解耦组件依赖。
  • 后台唤醒:即使应用处于后台,也能通过事件唤醒并执行任务。
  • 统一事件管理:提供通用的事件订阅、发布和取消订阅接口。
  • 跨设备同步:结合分布式能力,实现事件在多个设备间同步触发。

1.1 核心API介绍

HarmonyOS 5的事件处理主要依赖以下模块:

  • @ohos.commonEventManager:系统通用事件管理,如屏幕亮灭、网络变化等。
  • @ohos.remoteNotification:远程通知管理,用于处理推送事件。
  • @ohos.distributedDeviceManager:分布式设备管理,支持跨设备事件订阅。
  • BackgroundTaskManager:后台任务管理,确保事件处理在后台可持续运行。

2. 通用事件订阅与处理

通用事件(CommonEvent)是系统预定义的事件(如时间变化、网络状态变化),应用可订阅这些事件并在后台响应。

2.1 订阅系统事件

以下示例演示如何订阅屏幕亮灭事件,并在后台处理:

import commonEventManager from '@ohos.commonEventManager';
import commonEvent from '@ohos.commonEvent';
import { BusinessError } from '@ohos.base';@Entry
@Component
struct CommonEventDemo {// 订阅者对象private subscriber: commonEventManager.CommonEventSubscriber | null = null;// 订阅参数private subscribeInfo: commonEventManager.CommonEventSubscribeInfo = {events: [commonEvent.SCREEN_OFF, commonEvent.SCREEN_ON] // 订阅事件列表};// 组件初始化时订阅事件async aboutToAppear() {await this.subscribeCommonEvent();}// 订阅事件private async subscribeCommonEvent() {try {// 创建订阅者this.subscriber = await commonEventManager.createSubscriber(this.subscribeInfo);// 注册事件回调this.subscriber.on('receive', (event: commonEventManager.CommonEventData) => {console.log(`收到事件: ${event.event}`);this.handleScreenEvent(event.event);});console.log('通用事件订阅成功');} catch (error) {console.error(`订阅失败: ${(error as BusinessError).message}`);}}// 处理屏幕事件private handleScreenEvent(event: string) {// 后台处理逻辑:即使应用在后台也能执行switch (event) {case commonEvent.SCREEN_ON:// 屏幕点亮时处理this.onScreenOn();break;case commonEvent.SCREEN_OFF:// 屏幕熄灭时处理this.onScreenOff();break;}}private onScreenOn() {// 示例:屏幕亮起时刷新数据console.log('屏幕已点亮,开始后台数据同步...');this.refreshData();}private onScreenOff() {// 示例:屏幕熄灭时释放资源console.log('屏幕已熄灭,释放非必要资源...');this.releaseResources();}// 后台数据刷新private async refreshData() {// 实际项目中可从这里发起网络请求或更新本地数据console.log('执行后台数据刷新任务');}// 资源释放private releaseResources() {console.log('释放音频、传感器等资源');}// 取消订阅private async unsubscribeCommonEvent() {if (this.subscriber) {try {await commonEventManager.unsubscribe(this.subscriber);console.log('取消订阅成功');} catch (error) {console.error(`取消订阅失败: ${(error as BusinessError).message}`);}}}// 组件销毁时取消订阅aboutToDisappear() {this.unsubscribeCommonEvent();}build() {Column() {Text('通用事件订阅示例').fontSize(20).margin(10)Text('尝试开关屏幕查看控制台输出').fontSize(16).margin(10)}.width('100%').height('100%')}
}

2.2 支持订阅的常见系统事件

事件类型常量名触发条件后台处理能力
屏幕点亮SCREEN_ON屏幕从熄灭变亮支持
屏幕熄灭SCREEN_OFF屏幕熄灭支持
充电状态BATTERY_CHARGING开始充电支持
充电完成BATTERY_FULL电池充满支持
网络变化NETWORK_AVAILABLE网络连接状态变化支持
时间变化TIME_TICK系统时间每分钟变化支持
包安装PACKAGE_ADDED新应用安装支持
包移除PACKAGE_REMOVED应用被卸载支持

3. 自定义事件与跨设备事件

除了系统事件,应用还可以定义和发布自己的事件,并支持跨设备同步。

3.1 自定义事件发布与订阅

import commonEventManager from '@ohos.commonEventManager';
import commonEvent from '@ohos.commonEvent';
import { BusinessError } from '@ohos.base';// 定义自定义事件
const CUSTOM_EVENTS = {USER_LOGIN: 'com.example.APP.USER_LOGIN',DATA_UPDATED: 'com.example.APP.DATA_UPDATED'
};@Entry
@Component
struct CustomEventDemo {private subscriber: commonEventManager.CommonEventSubscriber | null = null;// 订阅自定义事件private async subscribeCustomEvents() {const subscribeInfo: commonEventManager.CommonEventSubscribeInfo = {events: [CUSTOM_EVENTS.USER_LOGIN, CUSTOM_EVENTS.DATA_UPDATED]};try {this.subscriber = await commonEventManager.createSubscriber(subscribeInfo);this.subscriber.on('receive', (event: commonEventManager.CommonEventData]) => {console.log(`收到自定义事件: ${event.event}`);console.log(`事件数据: ${JSON.stringify(event.parameters)}`);// 根据事件类型处理switch (event.event) {case CUSTOM_EVENTS.USER_LOGIN:this.handleUserLogin(event.parameters);break;case CUSTOM_EVENTS.DATA_UPDATED:this.handleDataUpdated(event.parameters);break;}});console.log('自定义事件订阅成功');} catch (error) {console.error(`自定义事件订阅失败: ${(error as BusinessError).message}`);}}// 发布自定义事件private async publishCustomEvent(event: string, params: Record<string, Object>) {try {await commonEventManager.publish(event, {parameters: params});console.log(`事件发布成功: ${event}`);} catch (error) {console.error(`事件发布失败: ${(error as BusinessError).message}`);}}// 处理用户登录事件private handleUserLogin(params: Record<string, Object>) {const username = params['username'] || '未知用户';console.log(`用户登录: ${username}`);// 执行后台任务,如同步用户数据}// 处理数据更新事件private handleDataUpdated(params: Record<string, Object>) {const dataType = params['dataType'] || '未知类型';console.log(`数据已更新: ${dataType}`);// 执行后台任务,如刷新缓存}build() {Column() {Button('发布用户登录事件').onClick(() => {this.publishCustomEvent(CUSTOM_EVENTS.USER_LOGIN, {username: '张三',userId: '12345',timestamp: Date.now()});}).margin(10).width('80%')Button('发布数据更新事件').onClick(() => {this.publishCustomEvent(CUSTOM_EVENTS.DATA_UPDATED, {dataType: '用户配置',updateCount: 5,timestamp: Date.now()});}).margin(10).width('80%')}.width('100%').height('100%').onAppear(() => {this.subscribeCustomEvents();}).onDisappear(() => {if (this.subscriber) {commonEventManager.unsubscribe(this.subscriber);}})}
}

3.2 跨设备事件同步

HarmonyOS的分布式能力允许事件在多个设备间同步触发。

import deviceManager from '@ohos.distributedDeviceManager';
import commonEventManager from '@ohos.commonEventManager';
import { BusinessError } from '@ohos.base';@Entry
@Component
struct DistributedEventDemo {// 获取可信设备列表private getTrustedDevices(): string[] {try {const devices = deviceManager.getTrustedDeviceListSync();return devices.map(device => device.deviceId);} catch (error) {console.error(`获取设备列表失败: ${(error as BusinessError).message}`);return [];}}// 发布跨设备事件private async publishDistributedEvent(event: string, params: Record<string, Object>) {try {const devices = this.getTrustedDevices();if (devices.length > 0) {// 向所有可信设备发布事件await commonEventManager.publish(event, {parameters: params,devices: devices // 指定目标设备});console.log(`跨设备事件发布成功,目标设备: ${devices.length}个`);} else {console.log('无可信设备,仅在本地发布');await commonEventManager.publish(event, { parameters: params });}} catch (error) {console.error(`跨设备事件发布失败: ${(error as BusinessError).message}`);}}// 订阅跨设备事件private async subscribeDistributedEvent() {const subscribeInfo: commonEventManager.CommonEventSubscribeInfo = {events: ['com.example.DISTRIBUTED_ACTION'],isDistributed: true // 关键:启用分布式订阅};try {const subscriber = await commonEventManager.createSubscriber(subscribeInfo);subscriber.on('receive', (event: commonEventManager.CommonEventData) => {console.log(`收到跨设备事件: ${event.event}`);console.log(`来源设备: ${event.deviceId}`);console.log(`事件数据: ${JSON.stringify(event.parameters)}`);// 处理跨设备事件this.handleDistributedEvent(event);});console.log('跨设备事件订阅成功');} catch (error) {console.error(`跨设备事件订阅失败: ${(error as BusinessError).message}`);}}private handleDistributedEvent(event: commonEventManager.CommonEventData) {// 实现跨设备事件处理逻辑console.log(`处理来自设备 ${event.deviceId} 的事件`);}
}

4. 后台持续任务处理

为确保事件处理在后台持续运行,需要使用BackgroundTaskManager申请后台权限。

4.1 后台任务配置与申请

首先,在module.json5中声明后台权限:

{"module": {"requestPermissions": [{"name": "ohos.permission.KEEP_BACKGROUND_RUNNING","reason": "$string:background_permission_reason","usedScene": {"abilities": ["MainAbility"],"when": "always"}}]}
}

然后在代码中申请后台任务权限:

import backgroundTaskManager from '@ohos.resources.backgroundTaskManager';
import { BusinessError } from '@ohos.base';@Entry
@Component
struct BackgroundEventDemo {private backgroundTaskId: number = 0;// 申请后台任务权限private async requestBackgroundPermission() {try {const result = await backgroundTaskManager.requestSuspendDelay();console.log('后台任务权限申请成功');// 注册后台任务回调this.backgroundTaskId = await backgroundTaskManager.startBackgroundRunning(backgroundTaskManager.BackgroundMode.DATA_PROCESSING,{// 任务配置isPersistent: true, // 持久化任务notificationContent: {title: '后台事件处理中',text: '应用正在后台处理事件'}});console.log(`后台任务启动成功,ID: ${this.backgroundTaskId}`);} catch (error) {console.error(`后台任务申请失败: ${(error as BusinessError).message}`);}}// 停止后台任务private async stopBackgroundTask() {if (this.backgroundTaskId !== 0) {try {await backgroundTaskManager.stopBackgroundRunning(this.backgroundTaskId);console.log('后台任务已停止');} catch (error) {console.error(`停止后台任务失败: ${(error as BusinessError).message}`);}}}build() {Column() {Button('启动后台事件监听').onClick(() => {this.requestBackgroundPermission();}).margin(10).width('80%')Button('停止后台监听').onClick(() => {this.stopBackgroundTask();}).margin(10).width('80%')}.width('100%').height('100%')}
}

5. 实战案例:后台数据同步器

以下是一个完整的后台数据同步器示例,结合事件订阅和后台任务:

import commonEventManager from '@ohos.commonEventManager';
import commonEvent from '@ohos.commonEvent';
import backgroundTaskManager from '@ohos.resources.backgroundTaskManager';
import { BusinessError } from '@ohos.base';@Entry
@Component
struct BackgroundDataSync {private subscriber: commonEventManager.CommonEventSubscriber | null = null;private backgroundTaskId: number = 0;@State syncStatus: string = '未启动';// 订阅网络变化事件private async setupNetworkListener() {const subscribeInfo: commonEventManager.CommonEventSubscribeInfo = {events: [commonEvent.NETWORK_AVAILABLE]};try {this.subscriber = await commonEventManager.createSubscriber(subscribeInfo);this.subscriber.on('receive', (event: commonEventManager.CommonEventData) => {console.log('网络状态变化,触发后台同步');this.syncDataInBackground();});console.log('网络监听器设置成功');} catch (error) {console.error(`网络监听设置失败: ${(error as BusinessError).message}`);}}// 后台数据同步private async syncDataInBackground() {this.syncStatus = '同步中...';try {// 模拟网络请求console.log('开始在后台同步数据');// 实际项目中这里可能是API调用或数据库操作await new Promise(resolve => setTimeout(resolve, 2000));console.log('后台数据同步完成');this.syncStatus = `最后同步: ${new Date().toLocaleTimeString()}`;// 发布同步完成事件await commonEventManager.publish('com.example.DATA_SYNC_COMPLETE', {result: 'success',timestamp: Date.now()});} catch (error) {console.error(`数据同步失败: ${(error as BusinessError).message}`);this.syncStatus = '同步失败';}}// 启动后台同步服务private async startSyncService() {// 申请后台权限try {this.backgroundTaskId = await backgroundTaskManager.startBackgroundRunning(backgroundTaskManager.BackgroundMode.DATA_PROCESSING,{isPersistent: true,notificationContent: {title: '数据同步服务运行中',text: '应用正在后台保持数据同步'}});await this.setupNetworkListener();this.syncStatus = '监听中,等待网络变化...';console.log('后台同步服务启动成功');} catch (error) {console.error(`后台服务启动失败: ${(error as BusinessError).message}`);}}// 停止服务private async stopSyncService() {if (this.subscriber) {await commonEventManager.unsubscribe(this.subscriber);this.subscriber = null;}if (this.backgroundTaskId !== 0) {await backgroundTaskManager.stopBackgroundRunning(this.backgroundTaskId);this.backgroundTaskId = 0;}this.syncStatus = '已停止';console.log('同步服务已停止');}aboutToDisappear() {this.stopSyncService();}build() {Column() {Text('后台数据同步器').fontSize(20).margin(10)Text(`状态: ${this.syncStatus}`).fontSize(16).margin(10)Button('启动后台同步').onClick(() => {this.startSyncService();}).margin(10).width('80%')Button('手动同步').onClick(() => {this.syncDataInBackground();}).margin(10).width('80%')Button('停止服务').onClick(() => {this.stopSyncService();}).margin(10).width('80%')}.width('100%').height('100%')}
}

6. 性能优化与最佳实践

  1. 事件过滤:精确订阅需要的事件类型,避免不必要的通知。

    // 好:精确订阅特定事件
    const subscribeInfo: commonEventManager.CommonEventSubscribeInfo = {events: [commonEvent.SCREEN_ON, commonEvent.SCREEN_OFF]
    };// 不好:订阅过多不必要的事件
    const subscribeInfo: commonEventManager.CommonEventSubscribeInfo = {events: [commonEvent.*] // 避免这样使用
    };
    
  2. 后台任务精简:后台处理逻辑应轻量高效,避免耗电和资源占用。

    // 好:高效的后台处理
    private async handleBackgroundEvent() {// 只执行必要的轻量操作await this.updateEssentialData();
    }// 不好:在后台执行重操作
    private async handleBackgroundEvent() {// 避免在后台执行大量计算或频繁网络请求await this.downloadLargeFiles(); // 不适合在后台执行
    }
    
  3. 及时取消订阅:在组件销毁或页面消失时取消事件订阅。

    aboutToDisappear() {if (this.subscriber) {commonEventManager.unsubscribe(this.subscriber);}
    }
    
  4. 分布式事件优化:跨设备事件应压缩数据量,减少网络传输。

    // 好:只发送必要数据
    await commonEventManager.publish('user_update', {parameters: {userId: '123',// 只发送变更字段updatedFields: ['name', 'avatar']}
    });
    
  5. 错误处理与重试:实现健壮的错误处理和重试机制。

    private async safePublishEvent(event: string, params: Record<string, Object>, retries = 3) {for (let i = 0; i < retries; i++) {try {await commonEventManager.publish(event, { parameters: params });return; // 成功则退出} catch (error) {if (i === retries - 1) {throw error; // 最后一次失败后抛出}await new Promise(resolve => setTimeout(resolve, 1000)); // 等待1秒后重试}}
    }
    

7. 总结

HarmonyOS 5的事件订阅与通知机制为后台事件处理提供了强大支持,关键要点包括:

  • 系统事件订阅:通过commonEventManager订阅系统事件,实现后台响应。
  • 自定义事件:支持应用定义和发布自己的事件,实现组件间解耦。
  • 跨设备同步:利用分布式能力实现事件在多设备间同步触发。
  • 后台持久化:使用BackgroundTaskManager确保事件处理在后台持续运行。
  • 性能优化:通过事件过滤、精简任务和及时取消订阅提升性能。

通过合理利用这些能力,开发者可以构建出响应迅速、跨设备协同的后台服务,提升用户体验和应用价值。

需要参加鸿蒙认证的请点击 鸿蒙认证链接


文章转载自:

http://rrdSc9N6.Lgmgn.cn
http://TmD2Gmny.Lgmgn.cn
http://150Gm0pm.Lgmgn.cn
http://3UtKIu7F.Lgmgn.cn
http://J6y8nMQd.Lgmgn.cn
http://nElqMBHH.Lgmgn.cn
http://s9YU3uKr.Lgmgn.cn
http://HhdBGOTI.Lgmgn.cn
http://5fuGqMm2.Lgmgn.cn
http://wD0OFdNd.Lgmgn.cn
http://hywYt1R4.Lgmgn.cn
http://dhGGbdTb.Lgmgn.cn
http://WzY9myt4.Lgmgn.cn
http://5GtMLbUE.Lgmgn.cn
http://bf0x7Vwo.Lgmgn.cn
http://bGejr7a5.Lgmgn.cn
http://syD0JCWk.Lgmgn.cn
http://QyAVWnxd.Lgmgn.cn
http://sawWvNHY.Lgmgn.cn
http://ayA3QHhE.Lgmgn.cn
http://J2RpDh4D.Lgmgn.cn
http://GoMCeCPk.Lgmgn.cn
http://LadqIJk2.Lgmgn.cn
http://pGHFgqTG.Lgmgn.cn
http://7lQ7sOh6.Lgmgn.cn
http://AhgVvidf.Lgmgn.cn
http://WZq5ytFa.Lgmgn.cn
http://m9VnMPCZ.Lgmgn.cn
http://o8La3I8R.Lgmgn.cn
http://F9yX3C8G.Lgmgn.cn
http://www.dtcms.com/a/385094.html

相关文章:

  • 医疗器械飞检常见问题:强生测量系统分析中30%误差的改进方法
  • 可视化数字平台如何重塑未来城市空间?
  • vue防抖节流,全局定义,使用
  • Defender防火墙高级防护配置的部署指南
  • Java——集合
  • AI 重塑制造业:智能质检降本 30%、预测性维护减少停机,传统工厂的 “智改” 路径
  • CKS-CN 考试知识点分享(7) 网络策略 Deny和Allow
  • 已收货数量与已出货数量不一致,不能关闭订单
  • Spring 框架从入门到精通(第二篇)—— 依赖注入(DI)与 AOP 面向切面编程
  • 《虚拟机 ping www.baidu.com失败?Linux ifcfg-ens33 网络配置实操教程》
  • 【LangChain指南】样例选择器(Example selectors)
  • 《深入剖析Kubernetes》02 崭露头角
  • Spring Boot日志
  • 跨域(CORS)和缓存中间件(Redis)深度解析
  • 010SecMain_InitializeDebugAgentPhase2
  • 检索融合方法- Distribution-Based Score Fusion (DBSF)
  • 排序实现java
  • 聊聊测试策略与测试方案
  • 考察软件售后服务,保障线上招标采购管理软件高效运行
  • 云HIS系统源码(HIS+LIS+EMR全套源码)门诊/住院/医保全流程打通
  • 单例模式,加锁
  • CV论文速递 | 13篇前沿论文精选:生成与处理、3D视觉、医学影像等核心方向(09.08-09.12)
  • Linux系统部分——冯诺依曼体系结构
  • 给图片url添加时间戳参数以防止缓存、清缓存
  • 硬件 - NSG2000 - NMOS代替继电器方案
  • ssh 故障排查和免密登陆
  • exists和in的区别及适用场景
  • 基于单片机的客车综合报警系统(论文+源码)
  • 积极践行“人工智能+”行动,山东大学数字人文教科研一体平台完成 AI 化升级
  • 晨曦中,它已劳作:一台有温度的机器人如何重塑我们的洁净日常