Laya.Handler 使用说明

概述

Laya.Handler 是 LayaAir 引擎中的事件处理器类,用于封装回调函数及其执行上下文。该类采用对象池管理机制,建议使用 Laya.Handler.create() 从对象池创建 Handler 对象,使用完毕后调用 recover() 回收,以减少对象创建开销。

目录


基础用法

创建 Handler

推荐使用静态方法 Laya.Handler.create() 从对象池创建:

// 从对象池创建 Handler,执行一次后自动回收
let handler = Laya.Handler.create(this, this.onComplete);

// 不自动回收(需手动调用 recover())
let handler = Laya.Handler.create(this, this.onComplete, null, false);

传递参数

// 创建时携带参数
let handler = Laya.Handler.create(
    this,           // caller - 执行上下文
    this.onLoad,    // method - 回调方法
    [1, 2, 3],      // args - 预定义参数
    false           // once - 是否执行一次后自动回收
);

执行 Handler

// 直接执行,使用预定义的 args
handler.run();

// 执行并携带额外数据
handler.runWith({ id: 100, name: "test" });

静态方法

create()

从对象池内创建一个 Handler。

static create(
    caller: any,              // 执行上下文 (this)
    method: Function | null,  // 回调方法
    args?: any[] | null,      // 传递给方法的参数
    once?: boolean            // 是否执行一次后自动回收,默认 true
): Handler

参数说明:

参数 类型 默认值 说明
caller any - 执行上下文,即回调函数中的 this
method Function | null - 回调函数
args any[] | null null 传递给回调函数的参数数组
once boolean true 是否执行一次后自动回收到对象池

示例:

// 场景1: 加载完成后回调
Laya.loader.load("res/atlas/comp.atlas",
    Laya.Handler.create(this, this.onLoaded)
);

// 场景2: 定时器回调
Laya.timer.once(1000, this, Laya.Handler.create(this, this.onTimeout));

// 场景3: 携带参数
Laya.Handler.create(
    this,
    this.onCallback,
    ["arg1", "arg2"],
    false  // 不自动回收
);

实例方法

run()

执行处理器,使用创建时传入的 args 参数。

run(): any

示例:

let handler = Laya.Handler.create(this, this.onData, [100, 200]);

// 执行时传入 [100, 200] 给 onData
handler.run();

private onData(a: number, b: number): void {
    console.log(a, b); // 输出: 100 200
}

runWith()

执行处理器,并携带额外数据。额外数据会追加到 args 后面传递给回调函数。

runWith(data: any): any

示例:

let handler = Laya.Handler.create(this, this.onData, [100]);

// 传入额外数据
handler.runWith(200);

private onData(a: number, b: number): void {
    console.log(a, b); // 输出: 100 200
}

recover()

清理并回收到 Handler 对象池内。

recover(): void

注意: 回收后不要继续使用该对象,否则可能导致不可预测的错误。由于鼠标事件也使用此对象池,不当的回收和调用可能影响鼠标事件的执行。

示例:

let handler = Laya.Handler.create(this, this.onCallback, null, false);

// 使用完毕后手动回收
handler.run();
handler.recover();

clear()

清理对象引用,重置为初始状态。

clear(): Handler

示例:

let handler = Laya.Handler.create(this, this.onCallback);
handler.clear(); // 重置 handler

setTo()

设置此对象的指定属性值。

setTo(
    caller: any,              // 执行上下文
    method: Function | null,  // 回调方法
    args: any[] | null,       // 参数数组
    once?: boolean            // 是否执行一次后回收
): Handler

示例:

let handler = new Laya.Handler();
handler.setTo(this, this.onCallback, [1, 2, 3], true);

属性说明

属性 类型 说明
caller Object | null 执行上下文对象 (this)
method Function | null 处理方法
args any[] | null 传递给处理方法的参数数组
once boolean 是否只执行一次,执行后自动回收

对象池管理

自动回收

使用 Laya.Handler.create() 创建时,默认 once=true,执行一次后会自动回收:

// 创建后执行一次自动回收
let handler = Laya.Handler.create(this, this.onComplete);

// Laya.loader 内部执行 handler.run() 后
// handler 会自动回收到对象池
Laya.loader.load("res.png", handler);

手动回收

当需要多次使用时,设置 once=false,使用完毕后手动调用 recover()

// 创建不自动回收的 Handler
let handler = Laya.Handler.create(this, this.onCallback, null, false);

// 多次执行
handler.run();
handler.run();

// 使用完毕后手动回收
handler.recover();

完整示例

示例1: 资源加载回调

export class LoadExample {
    constructor() {
        Laya.init(800, 600).then(() => {
            this.loadResources();
        });
    }

    private loadResources(): void {
        // 加载单个资源
        Laya.loader.load(
            "res/role.png",
            Laya.Handler.create(this, this.onLoaded)
        );

        // 加载多个资源
        Laya.loader.load([
            "res/bg.jpg",
            "res/music.mp3",
            "res/atlas/comp.atlas"
        ], Laya.Handler.create(this, this.onAllLoaded));
    }

    private onLoaded(texture: Laya.Texture): void {
        console.log("资源加载完成:", texture);
        let sprite = new Laya.Sprite();
        sprite.graphics.drawTexture(texture, 0, 0);
        Laya.stage.addChild(sprite);
    }

    private onAllLoaded(): void {
        console.log("所有资源加载完成");
    }
}

示例2: 动画完成回调

export class AnimationExample {
    constructor() {
        Laya.init(800, 600).then(() => {
            this.playAnimation();
        });
    }

    private playAnimation(): void {
        let animation = new Laya.Animation();
        animation.loadAtlas("res/fighter/fighter.json");

        // 播放完成后回调
        animation.on(Laya.Event.COMPLETE, this, this.onAnimComplete);

        animation.play();
        Laya.stage.addChild(animation);
    }

    private onAnimComplete(): void {
        console.log("动画播放完成");
    }
}

示例3: 定时器与 Handler

export class TimerExample {
    private count: number = 0;

    constructor() {
        Laya.init(800, 600).then(() => {
            this.startTimer();
        });
    }

    private startTimer(): void {
        // 延迟执行一次
        Laya.timer.once(1000, this, this.onTimeout);

        // 重复执行
        Laya.timer.loop(100, this, this.onTimerLoop);
    }

    private onTimeout(): void {
        console.log("1秒后执行");
    }

    private onTimerLoop(): void {
        this.count++;
        console.log("定时器执行:", this.count);

        if (this.count >= 10) {
            Laya.timer.clear(this, this.onTimerLoop);
        }
    }
}

示例4: 网络请求回调

export class HttpRequestExample {
    constructor() {
        Laya.init(800, 600).then(() => {
            this.sendRequest();
        });
    }

    private sendRequest(): void {
        let http = new Laya.HttpRequest();

        http.send(
            "https://api.example.com/data",
            null,
            "get",
            "text"
        );

        // 请求完成回调
        http.on(Laya.Event.COMPLETE, this, this.onRequestComplete);
        // 请求错误回调
        http.on(Laya.Event.ERROR, this, this.onRequestError);
    }

    private onRequestComplete(data: any): void {
        console.log("请求成功:", data);
    }

    private onRequestError(e: any): void {
        console.log("请求失败:", e);
    }
}

示例5: 使用 runWith 传递动态数据

export class RunWithExample {
    constructor() {
        Laya.init(800, 600).then(() => {
            this.createButtons();
        });
    }

    private createButtons(): void {
        for (let i = 0; i < 5; i++) {
            let btn = new Laya.Sprite();
            btn.graphics.drawRect(0, 0, 100, 40, "#2196F3");
            btn.pos(100, 100 + i * 60);

            // 使用 runWith 传递按钮索引
            btn.on(Laya.Event.CLICK, this, (btnIndex: number) => {
                this.onButtonClick(btnIndex);
            }, [i]); // 预定义参数

            Laya.stage.addChild(btn);
        }
    }

    private onButtonClick(index: number): void {
        console.log("点击了按钮:", index);
    }
}

示例6: 手动回收 Handler

export class ManualRecoverExample {
    private handler: Laya.Handler;

    constructor() {
        Laya.init(800, 600).then(() => {
            // 创建不自动回收的 Handler
            this.handler = Laya.Handler.create(
                this,
                this.onCallback,
                null,
                false  // once = false,不自动回收
            );

            // 可以多次执行
            this.handler.run();
            this.handler.run();

            // 使用完毕后手动回收
            this.handler.recover();
        });
    }

    private onCallback(): void {
        console.log("回调执行");
    }
}

示例7: 使用 setTo 重新配置

export class SetToExample {
    private handler: Laya.Handler;

    constructor() {
        Laya.init(800, 600).then(() => {
            this.handler = new Laya.Handler();

            // 第一次配置
            this.handler.setTo(this, this.onCallback1, null, false);
            this.handler.run();

            // 重新配置
            this.handler.setTo(this, this.onCallback2, ["hello"], true);
            this.handler.run();
        });
    }

    private onCallback1(): void {
        console.log("回调1");
    }

    private onCallback2(msg: string): void {
        console.log("回调2:", msg);
    }
}

注意事项

1. 回收后不要使用

Handler 被 recover() 回收后,不要继续使用,否则可能产生不可预测的错误:

let handler = Laya.Handler.create(this, this.onCallback, null, false);
handler.run();
handler.recover();

// ❌ 错误 - 回收后继续使用
handler.run();

// ✅ 正确 - 如需继续使用,创建新的 Handler
handler = Laya.Handler.create(this, this.onCallback);
handler.run();

2. 与鼠标事件共享对象池

Handler 的对象池也被鼠标事件使用,不当的回收可能影响鼠标事件:

// ⚠️ 注意:不要在 mouseDown 事件中 recover 正在使用的 handler
sprite.on(Laya.Event.MOUSE_DOWN, this, () => {
    // handler 可能被鼠标事件内部使用
    // 不建议在这里执行 recover 操作
});

3. 推荐使用 create() 而非 new

尽量使用 Laya.Handler.create() 从对象池获取,减少对象创建开销:

// ✅ 推荐 - 从对象池获取
let handler = Laya.Handler.create(this, this.onCallback);

// ❌ 不推荐 - 直接 new 创建
let handler = new Laya.Handler(this, this.onCallback);

4. 与 Laya.Delegate 的区别

特性 Laya.Handler Laya.Delegate
用途 单次回调封装 多个回调管理
对象池 支持对象池回收 无对象池
典型场景 资源加载、动画完成 自定义事件系统
执行方式 系统/手动调用 手动 invoke
// Handler - 单次回调
Laya.loader.load("res.png", Laya.Handler.create(this, this.onLoaded));

// Delegate - 多个监听器
let delegate = new Laya.Delegate();
delegate.add(this.onLoaded1, this);
delegate.add(this.onLoaded2, this);
delegate.invoke();
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐