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

时间:2013-05-21 23:02:00

标签: actionscript-3 events

我在小型上传软件中的想法是对所有任务(之前定义)始终使用相同的对象,我只是添加和删除事件并发出请求,因为参数总是相同的(相同的方法,相同的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+")");
            }

如何获得“未知功能”的名称?我担心会留下事件......

4 个答案:

答案 0 :(得分:2)

您可以设置几个简单的类来管理事件侦听器的集合。让我们调用集合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>[];
    }

}

这是代表项目的附带模型:

internal class EventBatchItem
{

    private var _target:IEventDispatcher;
    private var _type:String;
    private var _callback:Function;


    public function EventBatchItem(target:IEventDispatcher, type:String, callback:Function)
    {
        _target = target;
        _type = type;
        _callback = callback;
    }


    internal function dispose():void
    {
        _target = null;
        _callback = null;
    }


    internal function get target():IEventDispatcher{ return _target; }
    internal function get type():String{ return _type; }
    internal function get callback():Function{ return _callback; }

}

这样,您可以像这样添加事件监听器:

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();

答案 1 :(得分:1)

假设重置了处理程序并保留了对象的实例,您只需在addEventListener()函数中将useWeakReference设置为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);
        }

    }
}

答案 2 :(得分:1)

如果您知道可能作为监听器添加的所有功能,则可以删除所有这些功能。将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;

答案 3 :(得分:0)

查看我之前对Is There A Way To Remove Events Easier?的回答。基本上,没有简单的方法可以做到这一点。在那个答案中,我通过简单地覆盖事件监听器方法,将一个简单的方法放在一起来跟踪添加到类中的事件。使用该方法,您只需调用removeAllEventListeners()即可完成。它工作得相当好,只要你一直记得调用该函数(否则事情永远不会从内存中删除)。

然而,对于大多数情况来说,这是过度的。我目前正在将它用于大型应用程序并且它已经帮助很大,但是对于简单的事情,它只会为您的应用程序添加额外的计算和内存消耗。