AS3 scope and garbage collection - actionscript-3

Objetcs created inside a function are automatically marked for garbage collection if not referenced anywhere else?
Let´s say, I have a class called SubClass. in the constructor I create some displayObjects.
Then I instatiate SubClass somewhere. When I remove this SubClass instance, will the objects inside be marked for garbage collection?
thanks in advance!
cheers
Bruno

Yes, unless you have references to SubClass's members anywhere outside SubClass, or you keep an active reference to the outside of your class from within SubClass (or any objects within it).
A typical example of the latter is if SubClass subscribes to a Stage event; if the listener is not weak (5th argument of addEventListener) you will keep an active link between the stage and your SubClass instance, and even if you remove the object and null it, it will not be collected.
For simple listeners you can set that 5th argument to true, so the reference is weak and will be broken by the garbage collector. For more complex situations (or for example NetStreams, Loaders, Timeline audio, etc...), you need to create a way for the class to unlink itself for any outside objects and stop any process that could prevent collection, like a public destroy() method that closes requests, stopping media, removeListeners, etc...
But then again, for simple situations when you only have isolated childs, and no references to the outside of your class, simply removing your instance and nulling its reference should be enough for the garbage collection.

Related

Model-view design in Flash

I'm creating a simple game to learn Flash programming. To have a clean model/view separation, I want to create a Player class which simply holds data relevant to the user. I'm also creating a StatusView class which extends MovieClip and which coresponds to a movie clip symbol which I've created in my Flash project. Basically the StatusView will display the data of my Player class onscreen.
I'm used to doing this sort of thing using listeners, so I've found the EventDispatcher class and added one as a member of my Player class. I'd like to have my StatusView movie clip add an event listener to my Player class so that it can receive messages whenever I change the data in my Player class.
The problem is, there doesn't seem to be anywhere for me to put my Player class so that the StatusView can find it (to add the listener). Everything in the project is created directly by one of the movie clips, and the runtime seems to create these movie clips in an arbitrary order. For example, say I create a MovieClip symbol called GameView and I create the instance of the Player there, and GameView is the parent of StatusView. When StatusView is constructed, I'd like to be able to access the Player from it's parent, but at that point GameView hasn't had it's constructor code run yet. This is true even if I wait for the ADDED_TO_STAGE event.
I could put the game model code in a singleton, but this seems like a hack to me. Is there a best practices way in Flash that lets me create and access my game model independent of all the MovieClip symbol stuff?
If you want to pass the reference of the Model to the constructor of the View, but are not calling the constructor yourself (because you do not create the object via code) you are out of luck here.
You could instead simply define a method on your View to pass a reference of the Model object:
public function setModel(value:Model):void
usage:
view.setModel(player);
There's no "law" that you have to pass the Model to the constructor of the View.
You can also create a set function for convenience:
public function set model(value:Model):void
usage:
view.model = player;
I feel like I have to disagree on the Singleton. The purpose of a Singleton is to guarantee that there's only one instance of it in existence. That's it.
It is not there to pass reference around easily (because the method to get the single instance is static). This is (IMO) a bad practice.
You could make anythign static in order to pass it around "easily". But this would make a mess and nobody does that.
But suddenly, just because the singleton pattern uses a static method, a lot of people think it's a clever way to get to the reference. I beg to differ.
First of all, you could implement Player class as singleton if you need just one instance. I don't think that that looks like a hack (for example, in PureMVC framework each model is a singleton).
At second, you can create instances of Player class in some general class (manager) and send them to views.
P.S. Also, I want to note that you can extend your Player class from EventDisptacher without creating specific field "eventDispatcher" in Player class. I don't know what way is better, but this one is simpler, imho.

AS3 - Uses of addEventListener arguments

Now I am working on Flex 4 with AS3. In most of time I am using the addEventListener.
This listener default arguments are type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false. But most of the developers doesn't consider the last 3 arguments. But I want to know the uses of these 3 arguments?
Anyone call tell me answer?
Most of the times those three last parameters aren't necessary, because it's usually better to use a programming pattern to manage dependencies rather than leaving it to hard-to-debug spaghetti code that goes through many other classes.
Yet, there is a purpose for them and they can come in very handy:
useCapture - To register a listener with an event target’s ancestor for the capture phase of an event
dispatch, we set addEventListener( )’s third parameter, useCapture, to true, as in:
theAncestor.addEventListener(myEvent, MyListener, true);
The code causes MyListener( ) to be executed whenever AS3 dispatches myEvent targeted at one of theAncestor’s descendants before that descendant receives notification of the event.
priority - if you add more than one event listener to an object, the one that has higher priority will be triggered first. If you add two or more listeners with same priority, the one that was added first will trigger first. Just imagine that upon creating an object you've added an event listener, but later on you need to add another one and you want that new one to run first. Registering it with higher priority should do the trick.
weakReference - this is not a commonly used one, because Flash's garbage collector can run any time or even never. The problem is that regardless of any use of weak references, an object may continue to dispatch and listen to events until it gets garbage collected.
By default, an object that registers a listener
for a given event maintains a reference to that listener until it is explicitly unregistered
for that event—even when no other references to the listener remain in the program.
By setting the value to true the object will lose the reference to the listener when the object is eligible for garbage collection.
It's used to prevent memory leaks, but useWeakReference only has an effect when the listener object has a shorter lifetime than the dispatcher. It's a good idea to understand how to use it, but in practice I avoid it and simply write a method in my class that would remove all the added listeners.

AS3 Event architecture

I'm having difficulty with the last piece in the puzzle on AS3 events.
I understand target classes inherit from EventDispatch or implement IEventDispatch and can register (amongst other methods) event listeners.
However what do the target classes register with? If an Event happens, how does AS3 know to pass the Event to the target classes?
Regards,
shwell.
Read this article about event phases and it will make more sense:
http://livedocs.adobe.com/flex/3/html/help.html?content=events_02.html
Hope this helps. Have a great day.
You can look at how starling event works
starling even dispatcher
When a displayObject bubbles an event, it will check if the parent of the displayObject exist and add the parent to bubbleList if exist util the ancestor of displayObject is null.
The following code is in starling eventDispatcher
var element:DisplayObject = this as DisplayObject;
var chain:Vector.<EventDispatcher> = new <EventDispatcher>[element];
while ((element = element.parent) != null)
chain[int(length++)] = element;
In AS3, EventDispatcher is an implementation of the observer design pattern. This class implement the addEventLister, removeEventListener, dispatchEvent' andhasEventListener` methods. Internally, it also maintains a dictionary or similar data structure that contains the events which are currently being listened for, and a list of methods which have to be called when the event is dispatched. Something like this -
{"event1": [method7, method5, method3], "event2": [method3, method2], "event3": [method1]};
When addEventListener is called on an object, it creates a new key for the event in question and adds the method reference to its associated value list.
When dispatchEvent is called on the class, it fetches all the methods associated with the event and calls the methods attached with it. Each method is called with an instance of the Event class or its subclasses.
Removing an event listener obviously does the opposite of what adding does.
I guess you're missing of addEventListener() mechanics. This thing has a global side effect on event engine, registering a callback function along with caller this value to provide correct context of a fired event, with possible update of event.localX and event.localY properties by calling globalToLocal() either statically or dynamically, as the event bubbles up and down.
If you are, like me, confused about how does Flash player determine the target of an event - there is an internal "focus" pointer that determines which component of the SWF has keyboard focus, and that one is used to target keyboard events. For mouse events, most likely Flash engine calls getObjectsUnderPoint() to query for topmost IEventDispatcher compatible objects (not all of the DisplayObjects can process events), and that one is sent a mouse event, with the previous event's target to receive a say MouseEvent.ROLL_OUT or MouseEvent.MOUSE_OUT if the target has been changed. For other events, most likely the entire display list can react.
For objects in the display list, the following excerpt from Adobe is the answer "When Adobe® Flash® Player dispatches an Event object, that Event object makes a roundtrip journey from the root of the display list to the target node, checking each node for registered listeners.".
For non display objects, AS3 run time maintains a dictionary of all AS3 events containing bound variables. The bound variables are a reference to the event listeners.

AS3: Major Slowdown

I'm working on a Flash game, and after running my game for a while there is a huge drop in frame rate. There aren't a lot of MovieClips onscreen at once, but MovieClips are being replaced using removeChild and addChild often.
How can one test for problems such as memory leaks? And what are some good AS3 programming standards on this matter?
It seems like you're not preparing your instances of MovieClip for garbage collection. This thread could be extremely helpful to you.
Some of the basic things you want to cover when discarding a MovieClip (or any other Object) properly are:
Remove the object from the DisplayList (if it's a DisplayObject). This is done via what you're doing already, removeChild()
Remove any event listeners that have been applied to the Object. Best thing to do is keep on top of this right from the beginning; by that I mean, when you call addEventListener(), be sure to somewhere in the very near future add a sister removeEventListener() as well.
Remove reference to your Object. This includes, but is not limited to: reference to the Object via being part of an Array/Vector, reference via being stored in a property of another Object, etc.
A suggestion that I can offer is to have in the base class of your objects a method that handles all of this, eg remove() or deconstruct().
Here's an example:
public function deconstruct():void
{
if(parent)
parent.removeChild(this);
removeEventListener(MouseEvent.CLICK, _onClick);
}
And when you extend this class and need other dereferencing features, just build on your deconstruct() method:
override public function deconstruct():void
{
removeEventListener(MouseEvent.MOUSE_OVER, _mouseOver);
var i:int = someArray.indexOf(this);
someArray.splice(i, 1);
super.deconstruct();
}
http://gskinner.com/talks/resource-management/

Actionscript 3: Do you need to remove EventListeners?

In actionscript 3, I dynamically create objects to which I add EventListeners. These objects are added to arrays and might be removed again later. And others might be added later again. Each time I create an object, I add these EventListeners to them. However, is it necessary to remove these event listeners too, when deleting these objects? What happens when I lose all references to an object but don't delete these EventListeners? Do they stay somewhere in the memory, unreachable and unusuable, or does the GC clean them up?
Yes, you have to remove event listeners if you are not using weak references. GC won't clean up an object if there is a reference to it, and registering event listeners do create a reference to the object unless you set the useWeakReference parameter (the 5th parameter to the addEventListener method) to true while registering the event listener. Weak references won't be counted by the garbage collector.
//Using strong reference: needs to be removed by calling removeEventListener
sprite.addEventListener(Event.TYPE, listenerFunction, useCaptureBool, 0, false);
//Using a weak reference: no need to call removeEventListener
sprite.addEventListener(Event.TYPE, listenerFunction, useCaptureBool, 0, true);
When you have event listeners on an object you won't ever loose all references to it, so it'll stay in memory indefinitely. You need to make sure you always remove any listeners you set. You can set them using weak references, but that's not really a solution, it's better to remove them explicitly.