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

news/2025/9/24 16:32:16/文章来源:https://www.cnblogs.com/xpzll/p/19109477

本文将深入探讨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://www.mzph.cn/news/915950.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HarmonyOS后台任务管理:短时与长时任务实战指南

本文将深入探讨HarmonyOS 5(API 12)中的后台任务管理机制,详细讲解短时任务和长时任务的适用场景、实现方法、性能优化及最佳实践,帮助开发者构建高效节能的后台任务系统。1. 后台任务概述与分类 HarmonyOS提供了完…

案例分享 | 芯片企业官网优化

案例分享 | 芯片企业官网优化

Kali Linux 2025.3 发布 (Vagrant Nexmon) - 领先的渗透测试发行版

Kali Linux 2025.3 发布 (Vagrant & Nexmon) - 领先的渗透测试发行版Kali Linux 2025.3 发布 (Vagrant & Nexmon) - 领先的渗透测试发行版 The most advanced Penetration Testing Distribution 请访问原文链接…

C语言多线程同步详解:从互斥锁到条件变量

在多线程编程中,线程同步是确保多个线程正确协作的关键技术。当多个线程访问共享资源时,如果没有适当的同步机制,可能会导致数据竞争、死锁等问题。本文将详细介绍C语言中常用的线程同步技术。 为什么需要线程同步?…

收废铁的做网站有优点吗完整网站设计

一、卸载 1. sudo apt-get autoclean 如果你的硬盘空间不大的话&#xff0c;可以定期运行这个程序&#xff0c;将已经删除了的软件包的.deb安装文件从硬盘中删除掉。如果你仍然需要硬盘空间的话&#xff0c;可以试试apt-get clean&#xff0c;这会把你已安装的软件包的安装包也…

微网站的好处服务器架设国外做违法网站

文章目录 给飞行中的飞机换引擎安全意识十原则开发层面产品层面运维层面给飞行中的飞机换引擎 所谓给飞行中的飞机(或飞驰的汽车)换引擎,说的是我们需要对一个正在飞速发展的系统进行大幅度的架构改造,比如把 All-in-one 的架构改造成微服务架构,尽可能减少或者消除停服的…

企业网站建设前言宁海县做企业网站

数据挖掘主要侧重解决四类问题&#xff1a;分类、聚类、关联、预测。数据挖掘非常清晰的界定了它所能解决的几类问题。这是一个高度的归纳&#xff0c;数据挖掘的应用就是把这几类问题演绎的一个过程。 数据挖掘最重要的要素是分析人员的相关业务知识和思维模式。一般来说&…

确实网站的建设目标一个网站突然打不开

https://www.jb51.net/article/106525.htm 本文实例讲述了JS实现的五级联动菜单效果。分享给大家供大家参考&#xff0c;具体如下&#xff1a; js实现多级联动的方法很多&#xff0c;这里给出一种5级联动的例子&#xff0c;其实可以扩展成N级联动,在做项目的时候碰到了这样一…

Browser Use调用浏览器入门

用的是deepseek的api 一定要去官网看示例,网上的文章都比较老了,python的很多库版本基本都是不兼容的。新版的api跟老版的区别很大、、 运行的时候,要把电脑的代理关了,或者os设置一下不走代理。详情见 https://gi…

安防视频监控新时代:国标GB28181平台EasyGBS的可视化首页如何重塑运维与管理体验?

在视频监控迈入全面联网、集中管理的时代,GB/T28181国家标准已成为实现设备互联互通的核心基石。然而,仅仅实现接入是远远不够的,如何高效、直观地管理和运维海量视频资源成为新的挑战。本文将深入探讨基于GB28181协…

What is bad statistics

Bad statistics must involve self proof of the authors viewpoint and establish on a few of samples. Mathematical statistics only establishes on a huge sample space like PHYSICS. So the findings of PHYSI…

LazyForEach性能优化:解决长列表卡顿问题

本文将深入解析HarmonyOS中LazyForEach的工作原理、性能优势、实战优化技巧及常见问题解决方案,帮助你构建流畅的长列表体验。1. LazyForEach 核心优势与原理 LazyForEach 是鸿蒙ArkUI框架中为高性能列表渲染设计的核…

完整教程:SWR:React 数据获取的现代解决方案

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

Redis数据结构的最佳实践 - 公众号

本文已收录在Github,关注我,紧跟本系列专栏文章,咱们下篇再续!🚀 魔都架构师 | 全网30W技术追随者 🔧 大厂分布式系统/数据中台实战专家 🏆 主导交易系统百万级流量调优 & 车联网平台架构 🧠 AIGC应用…

PyTorch 神经网络工具箱 - 实践

PyTorch 神经网络工具箱 - 实践2025-09-24 16:21 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !importa…

java函数式编程的学习01

java函数式编程:在stream流中经常用到 对stream流的理解:操作集合的一种方法 stream流的用法:创建流、中间操作、终结操作 创建流的方式以及一些注意事项: 如果是集合通过.stream()方法来创建流,如果是数组,可以…

Manim实现镜面反射特效

本文将介绍如何使用ManimCE框架实现镜面反射特效,让你的动画更加生动有趣。 1. 实现原理 1.1. 对称点计算 实现镜面反射的核心是计算点关于直线的对称点。 代码中的symmetry_point函数通过向量投影的方法计算对称点:…

25Java基础之IO(二)

IO流-字符流 FileReader(文件字符输入流)作用:以内存为基准,可以把文件中的数据以字符的形式读入到内存中去。案例:读取一个字符//目标:文件字符输入流的使用,每次读取一个字符。 public class FileReaderDemo01 …

【git】统计项目下每个人提交行数

git log --format=%aN | sort -u | while read name; do echo -en "$name\t"; git log --author="$name" --pretty=tformat: --numstat | awk { add += $1; subs += $2; loc += $1 - $2 } END { p…

【P2860】[USACO06JAN] Redundant Paths G - Harvey

题意 给定一个连通图,求最少要加多少条边使得图无割边。 思路 首先,我们可以先缩点再进行考虑。 缩点后整个连通图变成一棵树,为了使连边后不出现割边,可以将所有度为 \(1\) 的点两两连边,如果度为 \(1\) 的点的个…