Actionscript 3 如何删除as3中具有未知函数的事件侦听器?

Actionscript 3 如何删除as3中具有未知函数的事件侦听器?,actionscript-3,events,Actionscript 3,Events,在一个小型上传软件中,我的想法是对所有任务(之前定义)始终使用相同的对象,我只是添加和删除事件并发出请求,因为参数总是相同的(相同的方法,相同的url…) 每当请求完成时,我都会删除侦听器,以便可以再次使用相同的对象 问题是当发生错误时,侦听器调用函数ioerror,但如果没有错误,我不知道应该调用什么函数: private function ioerror(e:IOErrorEvent){ e.target.removeEventListener(Event.C

在一个小型上传软件中,我的想法是对所有任务(之前定义)始终使用相同的对象,我只是添加和删除事件并发出请求,因为参数总是相同的(相同的方法,相同的url…)

每当请求完成时,我都会删除侦听器,以便可以再次使用相同的对象

问题是当发生错误时,侦听器调用函数ioerror,但如果没有错误,我不知道应该调用什么函数:

private function ioerror(e:IOErrorEvent){
                e.target.removeEventListener(Event.COMPLETE, unknownfuncion);
                e.target.removeEventListener(IOErrorEvent.IO_ERROR, ioerror);
                msg("Error somewhere ("+e.text+")");
            }

如何获得“未知函数”的名称?我担心的是留下事件…

假设处理程序被重置并且对象的一个实例被保留,您可以在垃圾收集函数中将
usewakreference
设置为true

然而,更好的设计模式是将服务方法抽象到类中

然后,调用
dispose
可以删除所有处理程序

package
{
    import flash.events.Event;
    import flash.events.EventDispatcher;
    import flash.events.IOErrorEvent;
    import flash.events.SecurityErrorEvent;
    import flash.net.URLLoader;
    import flash.net.URLRequest;
    import flash.net.URLRequestMethod;

    public class AbstractService extends EventDispatcher
    {

        public var data:Object;

        public var requestMethod:String = URLRequestMethod.GET;

        public var url:String;

        protected var urlLoader:URLLoader;

        protected var urlRequest:URLRequest;

        public function AbstractService()
        {
            super();

            urlLoader = new URLLoader();
            urlLoader.addEventListener(Event.COMPLETE, completeHandler);
            urlLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
            urlLoader.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
        }

        /**
         *
         * @param url
         * @param data String or URLVariables
         */
        public function load(url:String=null, data:Object=null, requestMethod:String=URLRequestMethod.GET):void
        {
            if (url)
                this.url = url;

            if (data)
                this.data = data;

            if (requestMethod)
                this.requestMethod = requestMethod;

            urlRequest = new URLRequest(this.url);
            urlRequest.data = this.data;
            urlRequest.method = this.requestMethod;

            urlLoader.load(urlRequest);
        }

        protected function completeHandler(event:Event):void
        {
        }

        protected function ioErrorHandler(event:IOErrorEvent):void
        {
        }

        protected function securityErrorHandler(event:SecurityErrorEvent):void
        {
        }

        public function dispose():void
        {
            urlLoader.removeEventListener(Event.COMPLETE, completeHandler);
            urlLoader.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
            urlLoader.removeEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
        }

    }
}

假设处理程序被重置并且对象的一个实例被保留,您可以在垃圾收集函数中将
usewakreference
设置为true

然而,更好的设计模式是将服务方法抽象到类中

然后,调用
dispose
可以删除所有处理程序

package
{
    import flash.events.Event;
    import flash.events.EventDispatcher;
    import flash.events.IOErrorEvent;
    import flash.events.SecurityErrorEvent;
    import flash.net.URLLoader;
    import flash.net.URLRequest;
    import flash.net.URLRequestMethod;

    public class AbstractService extends EventDispatcher
    {

        public var data:Object;

        public var requestMethod:String = URLRequestMethod.GET;

        public var url:String;

        protected var urlLoader:URLLoader;

        protected var urlRequest:URLRequest;

        public function AbstractService()
        {
            super();

            urlLoader = new URLLoader();
            urlLoader.addEventListener(Event.COMPLETE, completeHandler);
            urlLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
            urlLoader.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
        }

        /**
         *
         * @param url
         * @param data String or URLVariables
         */
        public function load(url:String=null, data:Object=null, requestMethod:String=URLRequestMethod.GET):void
        {
            if (url)
                this.url = url;

            if (data)
                this.data = data;

            if (requestMethod)
                this.requestMethod = requestMethod;

            urlRequest = new URLRequest(this.url);
            urlRequest.data = this.data;
            urlRequest.method = this.requestMethod;

            urlLoader.load(urlRequest);
        }

        protected function completeHandler(event:Event):void
        {
        }

        protected function ioErrorHandler(event:IOErrorEvent):void
        {
        }

        protected function securityErrorHandler(event:SecurityErrorEvent):void
        {
        }

        public function dispose():void
        {
            urlLoader.removeEventListener(Event.COMPLETE, completeHandler);
            urlLoader.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
            urlLoader.removeEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
        }

    }
}

如果您知道可以作为侦听器添加的所有函数,那么您可以删除它们。将removeEventListener()与实际未侦听的方法一起使用时,什么也不做。所以你可以用这样的东西:

private function ioerror(e:IOErrorEvent){
  // I know that Event.COMPLETE could be listened by function1, function2 or function3
  // I remove all of them
  e.target.removeEventListener(Event.COMPLETE, function1);
  e.target.removeEventListener(Event.COMPLETE, function2);
  e.target.removeEventListener(Event.COMPLETE, function3);
  e.target.removeEventListener(IOErrorEvent.IO_ERROR, ioerror);
  msg("Error somewhere ("+e.text+")");
}
另一种可能是跟踪在变量中实际侦听事件的方法

public function doSomething() {
  loader.addEventListener(Event.COMPLETE, onCompleteSomething);
  listeningComplete= onCompleteSomething;
}
public function doSomethingElse() {
  loader.addEventListener(Event.COMPLETE, onCompleteSomethingElse);
  listeningComplete= onCompleteSomethingElse;
}

private function ioerror(e:IOErrorEvent){
  e.target.removeEventListener(Event.COMPLETE, listeningComplete);
  e.target.removeEventListener(IOErrorEvent.IO_ERROR, ioerror);
  msg("Error somewhere ("+e.text+")");
}

private var listeningComplete:Function;

如果您知道可以作为侦听器添加的所有函数,那么您可以删除它们。将removeEventListener()与实际未侦听的方法一起使用时,什么也不做。所以你可以用这样的东西:

private function ioerror(e:IOErrorEvent){
  // I know that Event.COMPLETE could be listened by function1, function2 or function3
  // I remove all of them
  e.target.removeEventListener(Event.COMPLETE, function1);
  e.target.removeEventListener(Event.COMPLETE, function2);
  e.target.removeEventListener(Event.COMPLETE, function3);
  e.target.removeEventListener(IOErrorEvent.IO_ERROR, ioerror);
  msg("Error somewhere ("+e.text+")");
}
另一种可能是跟踪在变量中实际侦听事件的方法

public function doSomething() {
  loader.addEventListener(Event.COMPLETE, onCompleteSomething);
  listeningComplete= onCompleteSomething;
}
public function doSomethingElse() {
  loader.addEventListener(Event.COMPLETE, onCompleteSomethingElse);
  listeningComplete= onCompleteSomethingElse;
}

private function ioerror(e:IOErrorEvent){
  e.target.removeEventListener(Event.COMPLETE, listeningComplete);
  e.target.removeEventListener(IOErrorEvent.IO_ERROR, ioerror);
  msg("Error somewhere ("+e.text+")");
}

private var listeningComplete:Function;

看一看我以前对这个问题的回答。基本上,没有简单的方法可以做到这一点。在这个答案中,我提出了一种简单的方法来跟踪添加到类中的事件,方法是简单地重写事件侦听器方法。使用该方法,您只需调用
removeAllEventListeners()
,即可完成此操作。只要您始终记得调用该函数,它就工作得相当好(否则就永远不会从内存中删除内容)


然而,在大多数情况下,这都是过火了。我目前正在将它用于一个大型应用程序,它帮助很大,但简单来说,它只会给你的应用程序增加额外的计算和内存消耗,这是不必要的。

看看我以前对这个问题的回答。基本上,没有简单的方法可以做到这一点。在这个答案中,我提出了一种简单的方法来跟踪添加到类中的事件,方法是简单地重写事件侦听器方法。使用该方法,您只需调用
removeAllEventListeners()
,即可完成此操作。只要您始终记得调用该函数,它就工作得相当好(否则就永远不会从内存中删除内容)


然而,在大多数情况下,这都是过火了。我目前正在将它用于一个大型应用程序,它有很大的帮助,但对于一些简单的应用程序,它只会为您的应用程序添加不需要的额外计算和内存消耗。

您可以设置几个简单的类来管理一组事件侦听器。让我们调用集合
EventBatch
,它可能如下所示:

public class EventBatch
{

    private var _items:Vector.<EventBatchItem> = new <EventBatchItem>[];


    public function addListener(target:IEventDispatcher, type:String, callback:Function):void
    {
        var item:EventBatchItem = new EventBatchItem(target, type, callback);
        _items.push(item);

        target.addEventListener(type, callback);
    }


    public function removeAll():void
    {
        for each(var i:EventBatchItem in _items)
        {
            i.target.removeEventListener(i.type, i.callback);
            i.dispose();
        }

        _items = new <EventBatchItem>[];
    }

}
var batch:EventBatch = new EventBatch();
batch.addListener(urlLoader, Event.COMPLETE, completeHandler);
batch.addListener(urlLoader, SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
batch.addListener(urlLoader, IOErrorEvent.IO_ERROR, ioErrorHandler);
这样,您可以像这样添加事件侦听器:

public class EventBatch
{

    private var _items:Vector.<EventBatchItem> = new <EventBatchItem>[];


    public function addListener(target:IEventDispatcher, type:String, callback:Function):void
    {
        var item:EventBatchItem = new EventBatchItem(target, type, callback);
        _items.push(item);

        target.addEventListener(type, callback);
    }


    public function removeAll():void
    {
        for each(var i:EventBatchItem in _items)
        {
            i.target.removeEventListener(i.type, i.callback);
            i.dispose();
        }

        _items = new <EventBatchItem>[];
    }

}
var batch:EventBatch = new EventBatch();
batch.addListener(urlLoader, Event.COMPLETE, completeHandler);
batch.addListener(urlLoader, SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
batch.addListener(urlLoader, IOErrorEvent.IO_ERROR, ioErrorHandler);
在这些侦听器函数中,只需使用
.removeAll()
方法:

batch.removeAll();

您可以设置几个简单的类来管理事件侦听器的集合。让我们调用集合
EventBatch
,它可能如下所示:

public class EventBatch
{

    private var _items:Vector.<EventBatchItem> = new <EventBatchItem>[];


    public function addListener(target:IEventDispatcher, type:String, callback:Function):void
    {
        var item:EventBatchItem = new EventBatchItem(target, type, callback);
        _items.push(item);

        target.addEventListener(type, callback);
    }


    public function removeAll():void
    {
        for each(var i:EventBatchItem in _items)
        {
            i.target.removeEventListener(i.type, i.callback);
            i.dispose();
        }

        _items = new <EventBatchItem>[];
    }

}
var batch:EventBatch = new EventBatch();
batch.addListener(urlLoader, Event.COMPLETE, completeHandler);
batch.addListener(urlLoader, SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
batch.addListener(urlLoader, IOErrorEvent.IO_ERROR, ioErrorHandler);
这样,您可以像这样添加事件侦听器:

public class EventBatch
{

    private var _items:Vector.<EventBatchItem> = new <EventBatchItem>[];


    public function addListener(target:IEventDispatcher, type:String, callback:Function):void
    {
        var item:EventBatchItem = new EventBatchItem(target, type, callback);
        _items.push(item);

        target.addEventListener(type, callback);
    }


    public function removeAll():void
    {
        for each(var i:EventBatchItem in _items)
        {
            i.target.removeEventListener(i.type, i.callback);
            i.dispose();
        }

        _items = new <EventBatchItem>[];
    }

}
var batch:EventBatch = new EventBatch();
batch.addListener(urlLoader, Event.COMPLETE, completeHandler);
batch.addListener(urlLoader, SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
batch.addListener(urlLoader, IOErrorEvent.IO_ERROR, ioErrorHandler);
在这些侦听器函数中,只需使用
.removeAll()
方法:

batch.removeAll();

这根本行不通。询问者不需要知道调用事件的是什么,他们需要知道当前绑定到完全独立的事件侦听器的函数是什么,这样他们就可以删除特定的侦听器作为后续,我的评论是在建议编辑
arguments.callee
之前做出的。显然,我的评论不再适用。目前的答案是相当有效的,尽管它与Aralicia提供的答案没有什么不同(除了将其抽象为一个单独的方法,这将是处理这种情况的正确方法),但这根本不起作用。询问者不需要知道调用事件的是什么,他们需要知道当前绑定到完全独立的事件侦听器的函数是什么,这样他们就可以删除特定的侦听器作为后续,我的评论是在建议编辑
arguments.callee
之前做出的。显然,我的评论不再适用。目前的答案是相当有效的,尽管它与Aralicia提供的答案没有什么不同(除了将其抽象为一个单独的方法,这将是处理这种情况的正确方法),但这对于大型复杂软件非常有用。在我的例子中,我将创建一个简单的函数并添加所有需要的事件移除程序。到目前为止,我们必须始终以各种方式跟踪所有听众。谢谢。@GustavoPinent是的,正如我所提到的,当您在创建大规模应用程序时,手动跟踪可能添加或可能不添加的侦听器是不可行的,它非常有用。对于较小的应用程序,最好只是手动跟踪它们,因为您通常确切地知道要添加什么。有更好的设计来抽象这种类型的重用。@jasonstrugges,例如?我仍在尝试优化我的应用程序,所以欢迎对我的设计进行任何改进。也许,我不知道我是否“重新创建”了对象(obj:URLLoader)=