如何将参数传递给 flex/actionscript 中的事件侦听器函数?

Posted

技术标签:

【中文标题】如何将参数传递给 flex/actionscript 中的事件侦听器函数?【英文标题】:How to pass arguments into event listener function in flex/actionscript? 【发布时间】:2011-09-18 09:58:09 【问题描述】:

由于在使用 sql lite 时,如果您尝试同时执行一个函数,它会抛出一个错误,我只是试图创建一个函数来检查它是否正在执行,如果它在 10 毫秒内再次尝试,这正是如果我不必向函数传递任何参数,函数工作正常,但我很困惑如何将变量传递回它将执行的函数。

我想做:

timer.addEventListener(TimerEvent.TIMER, saveChat(username, chatBoxText));

但它只允许我这样做:

timer.addEventListener(TimerEvent.TIMER, saveChat);

它给了我这个编译错误:

1067: 对值的隐式强制 将 void 类型转换为不相关的类型 功能

我怎样才能让它通过这个限制?

这是我得到的:

public function saveChat(username:String, chatBoxText:String, e:TimerEvent=null):void

    var timer:Timer = new Timer(10, 1);
    timer.addEventListener(TimerEvent.TIMER, saveChat);

    if(!saveChatSql.executing)
    
        saveChatSql.text = "UPDATE active_chats SET convo = '"+chatBoxText+"' WHERE username = '"+username+"';";
        saveChatSql.execute();
    
    else timer.start();

【问题讨论】:

【参考方案1】:

监听器调用的函数只能有一个参数,即触发它的事件。

listener:Function — 处理事件的侦听器函数。 这个函数必须接受一个事件 对象作为它的唯一参数并且必须 什么都不返回,就像这个例子 节目:

function(evt:Event):void

Source

您可以通过让事件调用的函数调用具有所需参数的另一个函数来解决此问题:

timer.addEventListener(TimerEvent.TIMER, _saveChat);
function _saveChat(e:TimerEvent):void

    saveChat(arg, arg, arg);


function saveChat(arg1:type, arg2:type, arg3:type):void

    // Your logic.

您可以做的另一件事是创建一个扩展 flash.events.Event 的自定义事件类并在其中创建您需要的属性。

package

    import flash.events.Event;

    public class CustomEvent extends Event
    
        // Your custom event 'types'.
        public static const SAVE_CHAT:String = "saveChat";

        // Your custom properties.
        public var username:String;
        public var chatBoxText:String;

        // Constructor.
        public function CustomEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false):void
        
            super(type, bubbles, cancelable);
        
    

然后您可以使用定义的属性来调度它:

timer.addEventListener(TimerEvent.TIMER, _saveChat);
function _saveChat(e:TimerEvent):void

    var evt:CustomEvent = new CustomEvent(CustomEvent.SAVE_CHAT);

    evt.username = "Marty";
    evt.chatBoxText = "Custom events are easy.";

    dispatchEvent(evt);

然后听一听:

addEventListener(CustomEvent.SAVE_CHAT, saveChat);
function saveChat(e:CustomEvent):void

    trace(e.username + ": " + e.chatBoxText);
    // Output: Marty: Custom events are easy.

【讨论】:

【参考方案2】:

实际上,您可以将其他参数传递给事件侦听器,而无需使用 Actionscript 的动态函数构造来创建自定义事件。

private function addArguments(method:Function, additionalArguments:Array):Function

  return function(event:Event):void method.apply(null, [event].concat(additionalArguments));

在为警报窗口设置 closeHandler 时,我们调用 addArguments() 方法并传入一个数组,其中包含我们要传递给 closeHandler 的所有参数。 addHandler() 方法将返回我们将在包含参数的警报窗口关闭时调用的函数。

protected function btnOK_clickHandler(event:MouseEvent):void

  Alert.show("Would you like to reverse the text you just entered?", "", Alert.YES | Alert.NO, null, addArguments(alertCloseHandler, [txtInput.text]), null, Alert.YES);
  txtInput.text = "";

【讨论】:

【参考方案3】:

1067: 将 void 类型的值隐式强制转换为不相关的 Function 类型

请注意你得到的错误:它说Function 是一个类型,而addEventListener() 想要它。尽管您的听众返回 void,但它是 Function!那么,返回监听器怎么样?

timer.addEventListener(TimerEvent.TIMER, saveChat(username, chatBoxText));
function saveChat(username:String, chatBoxText:String):Function 
  return function(e:TimerEvent):void 
    // Do everything that uses "e", "chatBoxText" and "username" here!
  ;

就这么简单。它适用于任何类型的事件。 而且没有关闭问题。

注意removeEventListener()

不要尝试做timer.removeEventListener(TimerEvent.TIMER, saveChat(username, chatBoxText))。它不会识别您的函数,因为您每次使用saveChat() 时都会在其上传递一个新函数。相反,只需将其引用取出到变量中即可完成:

var functionSaveChat:Function = saveChat(username, chatBoxText);
timer.addEventListener(TimerEvent.TIMER, functionSaveChat);
//trace(timer.hasEventListener(TimerEvent.TIMER));
timer.removeEventListener(TimerEvent.TIMER, functionSaveChat);
//trace(timer.hasEventListener(TimerEvent.TIMER));

【讨论】:

哇,这真的很有帮助。谢谢!我从来没有看到过这种可能性的评论。使用这个有什么缺点吗?也许有一些内存泄漏或类似的东西? @OMA 我多年来一直很好。如果您想确定,请使用memory profiler 进行测试。 太好了,谢谢。就我而言,就像您建议的那样,我没有将对函数的引用保存在变量中,而是使用 event.currentTarget.removeEventListener(MyListener, arguments['callee']);从函数内部移除监听器。 就我而言,我在你们使用的两种方式之间切换。主要是 arguments.callee 是简单的方法。但是当我不能从自身中删除监听器时,我会求助于变量中的引用。两者都很棒。【参考方案4】:

你可以试试这个:

var timerHandler:Function = function (event:TimerEvent):void

   saveChat(username,chatBoxText,event);


timer.addEventListener(TimerEvent.TIMER, timerHandler);

【讨论】:

【参考方案5】:

以上调用 saveChat(arg, arg, arg) 不适合我,我需要传递此方法中没有的参数,但我有另一个解决方案

我总是使用额外的方法 passParameters 来添加新参数:

public function passParameters(method:Function,additionalArguments:Array):Function
return function(event:Event):void
    method.apply(null, [event].concat(additionalArguments));

对此的解释在这里 - 它简单且始终有效 http://sinfinity.pl/blog/2012/03/28/adding-parameters-to-event-listener-in-flex-air-as3/

【讨论】:

以上是关于如何将参数传递给 flex/actionscript 中的事件侦听器函数?的主要内容,如果未能解决你的问题,请参考以下文章

如何将参数传递给进程

如何通过反射将参数传递给方法

如何将参数传递给 erlang os:cmd()?

如何使用 SwiftUI 将参数传递给 Button 的操作

如何将两个参数传递给 Pool.starmap()?

如何将参数传递给 JSP 组件?