系统中提供更安全的事件监听器方法(避免内存泄露)
This commit is contained in:
@@ -5,6 +5,17 @@ import type { Scene } from '../Scene';
|
|||||||
import type { ISystemBase } from '../../Types';
|
import type { ISystemBase } from '../../Types';
|
||||||
import type { QuerySystem } from '../Core/QuerySystem';
|
import type { QuerySystem } from '../Core/QuerySystem';
|
||||||
import { getSystemInstanceTypeName } from '../Decorators';
|
import { getSystemInstanceTypeName } from '../Decorators';
|
||||||
|
import type { EventListenerConfig, TypeSafeEventSystem, EventHandler } from '../Core/EventSystem';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 事件监听器记录
|
||||||
|
*/
|
||||||
|
interface EventListenerRecord {
|
||||||
|
eventSystem: TypeSafeEventSystem;
|
||||||
|
eventType: string;
|
||||||
|
handler: EventHandler;
|
||||||
|
listenerRef: string;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 实体系统的基类
|
* 实体系统的基类
|
||||||
@@ -37,6 +48,7 @@ export abstract class EntitySystem implements ISystemBase {
|
|||||||
private _initialized: boolean = false;
|
private _initialized: boolean = false;
|
||||||
private _matcher: Matcher;
|
private _matcher: Matcher;
|
||||||
private _trackedEntities: Set<Entity> = new Set();
|
private _trackedEntities: Set<Entity> = new Set();
|
||||||
|
private _eventListeners: EventListenerRecord[] = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取系统处理的实体列表(动态查询)
|
* 获取系统处理的实体列表(动态查询)
|
||||||
@@ -152,6 +164,12 @@ export abstract class EntitySystem implements ISystemBase {
|
|||||||
public reset(): void {
|
public reset(): void {
|
||||||
this._initialized = false;
|
this._initialized = false;
|
||||||
this._trackedEntities.clear();
|
this._trackedEntities.clear();
|
||||||
|
|
||||||
|
// 清理所有事件监听器
|
||||||
|
this.cleanupEventListeners();
|
||||||
|
|
||||||
|
// 调用用户可重写的销毁方法
|
||||||
|
this.onDestroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -543,4 +561,90 @@ export abstract class EntitySystem implements ISystemBase {
|
|||||||
protected onRemoved(entity: Entity): void {
|
protected onRemoved(entity: Entity): void {
|
||||||
// 子类可以重写此方法
|
// 子类可以重写此方法
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加事件监听器
|
||||||
|
*
|
||||||
|
* 推荐使用此方法而不是直接调用eventSystem.on(),
|
||||||
|
* 这样可以确保系统移除时自动清理监听器,避免内存泄漏。
|
||||||
|
*
|
||||||
|
* @param eventType 事件类型
|
||||||
|
* @param handler 事件处理函数
|
||||||
|
* @param config 监听器配置
|
||||||
|
*/
|
||||||
|
protected addEventListener<T = any>(
|
||||||
|
eventType: string,
|
||||||
|
handler: EventHandler<T>,
|
||||||
|
config?: EventListenerConfig
|
||||||
|
): void {
|
||||||
|
if (!this.scene?.eventSystem) {
|
||||||
|
console.warn(`[${this.systemName}] Cannot add event listener: scene.eventSystem not available`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const listenerRef = this.scene.eventSystem.on(eventType, handler, config);
|
||||||
|
|
||||||
|
// 跟踪监听器以便后续清理
|
||||||
|
if (listenerRef) {
|
||||||
|
this._eventListeners.push({
|
||||||
|
eventSystem: this.scene.eventSystem,
|
||||||
|
eventType,
|
||||||
|
handler,
|
||||||
|
listenerRef
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 移除特定的事件监听器
|
||||||
|
*
|
||||||
|
* @param eventType 事件类型
|
||||||
|
* @param handler 事件处理函数
|
||||||
|
*/
|
||||||
|
protected removeEventListener<T = any>(
|
||||||
|
eventType: string,
|
||||||
|
handler: EventHandler<T>
|
||||||
|
): void {
|
||||||
|
const listenerIndex = this._eventListeners.findIndex(
|
||||||
|
listener => listener.eventType === eventType && listener.handler === handler
|
||||||
|
);
|
||||||
|
|
||||||
|
if (listenerIndex >= 0) {
|
||||||
|
const listener = this._eventListeners[listenerIndex];
|
||||||
|
|
||||||
|
// 从事件系统中移除
|
||||||
|
listener.eventSystem.off(eventType, listener.listenerRef);
|
||||||
|
|
||||||
|
// 从跟踪列表中移除
|
||||||
|
this._eventListeners.splice(listenerIndex, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清理所有事件监听器
|
||||||
|
*
|
||||||
|
* 系统移除时自动调用,清理所有通过addEventListener添加的监听器。
|
||||||
|
*/
|
||||||
|
private cleanupEventListeners(): void {
|
||||||
|
for (const listener of this._eventListeners) {
|
||||||
|
try {
|
||||||
|
listener.eventSystem.off(listener.eventType, listener.listenerRef);
|
||||||
|
} catch (error) {
|
||||||
|
console.warn(`[${this.systemName}] Failed to remove event listener for "${listener.eventType}":`, error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清空跟踪列表
|
||||||
|
this._eventListeners.length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 系统销毁时的回调
|
||||||
|
*
|
||||||
|
* 当系统从场景中移除时调用,子类可以重写此方法进行清理操作。
|
||||||
|
* 注意:事件监听器会被框架自动清理,无需手动处理。
|
||||||
|
*/
|
||||||
|
protected onDestroy(): void {
|
||||||
|
// 子类可以重写此方法进行清理操作
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user