What is (or) the advantage (s) of using weak references in EventListeners in AS3?

I taught actioncript 3 myself in the last month or so and recently ran into a problem when an object continued to do something after I thought it was deleted. I realized that the problem was caused by the event listener using the default value useWeakReference = false, and I wonder why this is the default value. What is the advantage of not using a weak link? and why is it defaulted? it seems to me that in general you would like to use weak links, so something is missing for me.

Thanks, -Ted

+4
source share
4 answers

the point is that weak links are expensive ... they both slower and consume more space ... here is some control code:

package { //{ region imports import flash.display.Sprite; import flash.events.Event; import flash.events.EventDispatcher; import flash.system.System; import flash.utils.*; //} endregion public class Main extends Sprite { public function Main():void { switch (0) { case 0: this.benchmarkDispatchers(false); break; case 1: this.benchmarkDispatchers(true); break; case 2: this.benchmarkDictionaries(false); break; case 3: this.benchmarkDictionaries(true); break; } } private function benchmarkDictionaries(weakKeys:Boolean, size:uint = 1000000):void { var a:Array = []; for (var i:int = 0; i < size; i++) a.push( { "foo":i } ); var d:Dictionary = new Dictionary(weakKeys); var start:int = getTimer(); var mem0:int = System.totalMemory; for (var j:int = 0; j < size; j++) d[a[j]] = j; trace("adding "+size+" keys took "+(getTimer()-start)+" msecs and "+(System.totalMemory-mem0)+" B of memory with weakKeys == "+weakKeys); } private function benchmarkDispatchers(weakRef:Boolean, size:uint = 100000):void { var a:Array = []; var f:Function = function (i:*):Function { return function ():void { i; } } for (var i:int = 0; i < size; i++) a.push( f(i) ); var e:EventDispatcher = new EventDispatcher(); var start:int = getTimer(); var mem0:uint = System.totalMemory; for (var j:int = 0; j < size; j++) e.addEventListener("foo", a[j], false, 0, weakRef); trace("adding " + size + " event handlers took " + (getTimer() - start) + " msecs and " + (System.totalMemory - mem0) + " B of memory with weakKeys == " + weakRef); } } } 

this is what i get on my machine:

 adding 100000 event handlers took 679 msecs and 6922240 B of memory with weakKeys == false adding 100000 event handlers took 1348 msecs and 13606912 B of memory with weakKeys == true adding 1000000 keys took 283 msecs and 16781312 B of memory with weakKeys == false adding 1000000 keys took 906 msecs and 42164224 B of memory with weakKeys == true 

the results are a little more radical for dictionaries, most likely due to the lack of ActionScript calls with respect to time, and since some storage costs in registering an event handler reduce the difference between the required memory (as you can see, these are 69 bytes / handler and 16 bytes / key when comparing weak links) ...

so yes, it’s about performance ... using weak links is not a healthy fact that you don’t have to delete the listener for the object to die ... if you want to have a scalable application, you need to do such things yourself, and if you want it to be 100% reliable, you cannot hope that the GC will do your work, but you need to do the cleaning yourself ... and also, if you have a good hierarchy in your application, you probably don't run into this problem often often ... in a way, it's a luxury l if you do not want to spend time creating an appropriate object because problems that cannot be solved without weak links are rare ... it should be used when it offers a real advantage, and not just because of laziness ... I I think this is wrong by default ...

hope this helps ...;)

Greetz

back2dos

+6
source

You are right, usually you want to use weak links, probably about 99% of the time. I think the default value should really be set to true, but we just need to deal with it wrong. I suggest you get used to always using weak links, and you will save a few headaches and see some performance benefits, as this helps in managing garbage collection.

So, when do you want this to be false? Basically, anytime you don’t want things to be automatically cleaned up, when the garbage collector decides that you no longer use it. These situations are rare, and when the time comes, you will probably just find out.

HOWEVER . This may not solve your own problem. The garbage collector only works at unpredictable intervals, so although you delete all references to the object, it can still handle these events until it is cleared. It is best to remove event listeners yourself so that they do not start again. You can do this with the removeEventListener method.

Good luck

Tyler

+2
source

Weak links can bite you when performing asynchronous operations, since anything that is not done to bind to the object's schedule can be collected at any time.

In particular, never use weak references for event handlers that have limited functions:

 function weakRefSample() : void { var evntDispatcher : IEventDispatcher = new EventDispatcher(); evntDispatcher.addEventListener(Event.COMPLETE, scopeHandler, false, 0, true); function scopedHandler(event : Event) : void { } } 

There are two things in the above example:

  • scopeHandler can be assembled because it is not bound to an object graph
  • the scope of the weakRefSample function can be collected because nothing requires its existence (nothing uses a scopedHandler), so evntDispatcher can be built. If evntDispatcher was expecting another asynchronous event, it could be collected before the event ended.
+2
source

I found that Timer instances that have weak references to event listeners sometimes do not fire the event.

0
source

All Articles