- 本文所有代码案例均基于Api12。
在鸿蒙开发中,经常会遇到发送通知给其他类的需求。
大部分时候,我们会根据页面生命周期,在多个页面添加同一个消息事件监听,离开页面时只取消当前页面的监听,其他页面添加过监听的页面需要继续保持监听状态。
系统自带的通知里,如果一个消息事件添加了多处监听,在任意一处位置取消时,会同时取消该事件所有位置的监听。
所以,需要有一个通知管理类来承担这份工作。可以识别消息事件,还可以支持不同对象的注册和取消。
我自己写一个通知管理类解决这个问题。
调用方式如下:
// 页面构建时
aboutToAppear(): void {
CustomNotification.register("test_event",this.getUniqueId(),()=>{
// xxxxxx
})
}
// 页面销毁时
aboutToDisappear(): void {
CustomNotification.unRegister("test_event",this.getUniqueId())
}
// 发送消息时
CustomNotification.emit("test_event")
-
参数说明: 1、注册方法中,第一个参数,是消息事件的key,同一个key的事件可以在多处注册;第二个参数是监听对象的id,用于区分同一个key下面的不同回调持有对象;第三个参数是回调方法,自己填写当前业务代码,这个参数是function,要自己注意对齐参数。 2、注销方法中,同样的需要填入消息事件的key和持有对象id。 3、这里的持有对象id使用了this.getUniqueId(),这个id是UI的唯一id,不用担心重复,省去了每次自己命名id的烦恼。
-
class里没有UniqueId,要给class对象添加通知怎么办? 我自己写的时候,class有时候也需要添加监听,所以我把这个id类型写成了联合类型 (type EventID = string | number) 根据业务场景,用字符串自定义一个key即可,比如:
CustomNotification.register("test_event",this.getUniqueId(),()=>{
// xxxxxx
})
以下是完整的通知类代码:
export namespace CustomNotification {
/**
* 事件id类型
*/
type EventID = string | number
/**
* 监听事件
*/
class Event {
/**
* 事件id
*/
id: EventID
/**
* 事件回调
*/
handle: Function
constructor(id: EventID, handle: Function) {
this.id = id
this.handle = handle
}
}
/**
* 通知
*/
class Notification {
/**
* 通知名
*/
name: string
/**
* 事件队列
*/
events: Event[] = []
constructor(name: string) {
this.name = name
}
}
/**
* 通知寄存处
*/
let notifications: Notification[] = []
/**
* 注册通知
* @param name 通知名
* @param id 唯一(相对于这个通知名)的监听id,同一个对象内添加和移除时的id应该一致,重复的id不会影响监听,
* 但可能会导致被其他地方相同id的监听移除
* @param handle 回调方法
*/
export function register(
name: string,
id: EventID,
handle: Function
) {
// 检查通知状态
checkNotification(name)
notifications.forEach((model: Notification) => {
// 根据通知名找到通知
if (model.name == name) {
// 把监听事件插入通知
model.events.push(new Event(id, handle))
}
})
}
/**
* 检查通知状态,如果之前没有,就新增一个通知模型
* @param name 通知名
*/
function checkNotification(name: string) {
let models = notifications.filter((model) => {
return model.name == name
})
// 找不到就新增
if (models.length == 0) {
notifications.push(new Notification(name))
}
}
/**
* 调用通知消息
* @param name 通知名
* @param record 调用时的入参
*/
export function emit(
name: string,
...argArray: ESObject[]
) {
notifications.forEach((notification: Notification) => {
// 根据通知名找到通知
if (notification.name == name) {
// 调用通知的所有监听事件,并发送参数
notification.events.forEach((event) => {
// 调用时不区分id,这个通知所有的监听事件都会被触发
event.handle(...argArray)
})
}
})
}
/**
* 取消监听事件
* @param name 通知名
* @param id 事件id
*/
export function unRegister(
name: string,
id: EventID
) {
notifications.forEach((notification: Notification) => {
// 根据通知名找到通知
if (notification.name == name) {
// 根据id移除监听事件
notification.events = notification.events.filter((event) => {
return event.id != id
})
}
})
// 清理已经没有监听的空通知
notifications = notifications.filter((model) => {
return model.events.length > 0
})
}
}