存档

文章标签 ‘垃圾回收’

了解ActionScript的垃圾回收集机制

2010年2月18日 1 条评论

http://www.davidpett.com/actionscript-3-managing-memory/

I have been doing a lot of work in try­ing to min­i­mize mem­o­ry and file size in my flash/ac­tion­script pro­jects, be­cause of the struc­ture of ac­tion­script 3 most of this is a man­u­al pro­cess. One of the first things you can do is when adding an event lis­ten­er, use the op­tion­al pa­ram­e­ters:

_btn.addEventListener(MouseEvent.CLICK, btnClick, false, 0, true);

The last op­tion­al pa­ram­e­ter in the ad­dE­ventLis­ten­er func­tion is useWeakRef­er­ence, which by de­fault is set to false, ac­cord­ing to the Ac­tion­Script 3.0 Doc­u­men­ta­tion, this pa­ram­e­ter “De­ter­mines whether the ref­er­ence to the lis­ten­er is strong or weak. A strong ref­er­ence (the de­fault) pre­vents your lis­ten­er from being garbage-​col­lect­ed. A weak ref­er­ence does not.”

An­oth­er stan­dard that I have ime­ment­ed is to use the RE­MOVED_FROM_STAGE event in every class that I write. In this class I re­move any dis­play ob­jects that I have added and re­move all event lis­ten­ers that those dis­play ob­jects have, be­cause just re­mov­ing an ob­ject does not do this and hose event lis­ten­ers will still be there takin up mem­o­ry and can hin­der per­for­mance.

package
{
    import flash.display.*;
    import flash.events.*;

    public class MyClass extends Sprite
    {
        private var _btn:Sprite;
//———————————–
//    CONSTRUCTOR
//———————————–
        public function MyClass():void
        {
            addEventListener(Event.ADDED_TO_STAGE, init, false, 0, true);
        }
//———————————–
//    INIT
//———————————–
        private function init(e:Event):void
        {
            removeEventListener(Event.ADDED_TO_STAGE, init);
            addEventListener(Event.REMOVED_FROM_STAGE, dispose, false, 0, true);

            _btn = new Sprite();
            _btn.addEventListener(MouseEvent.MOUSE_OVER, btnOver, false, 0, true);
            _btn.addEventListener(MouseEvent.MOUSE_OUT, btnOut, false, 0, true);
            _btn.addEventListener(MouseEvent.CLICK, btnClick, false, 0, true);
            _btn.buttonMode = true;
            addChild(_btn);
        }
//———————————–
//    DISPOSE
//———————————–
        private function dispose(e:Event):void
        {
            removeEventListener(Event.ADDED_TO_STAGE, init);
            removeEventListener(Event.REMOVED_FROM_STAGE, dispose);

            if(_btn)
            {
                _btn.removeEventListener(MouseEvent.MOUSE_OVER, btnOver);
                _btn.removeEventListener(MouseEvent.MOUSE_OUT, btnOut);
                _btn.removeEventListener(MouseEvent.CLICK, btnClick);
                try
                {
                    removeChild(_btn);
                }
                catch(e:Error){trace("error: MyClass: dispose: removeChild(_btn): " + e)}
                _btn = null;
            }
        }
    }
}

 

http://dispatchevent.org/mims/creating-weak-references-in-as3/

 

For those of you not familiar with the concept, a weak-reference is a reference to an object that will not hold the linked object in memory when that object is garbage collected.

There are only two ways to create a weak reference in AS3. The first is with the IEventDispatcher.addEventListener() method which allows you to create a weak link between the dispatcher and the listener. To quote the AS3 Bible:

ActionScript 3.0 introduces the concept of weak and strong memory references. Normally, an object will be garbage collected if there are no references to the object. That is, when no objects are using a variable, it gets thrown out. Weak references allow you to reference an object but the object will still be eligible for garbage collection unless another object holds a strong reference to the object. By setting the [addEventListener() method's] useWeakReference flag to true, you will create a weak link between the event broadcaster and the event listener. That way, if an dispatcher is deleted while there are still listeners attached, the weak reference will allow it to be garbage collected. This helps to prevent memory leaks.

The other way is with the objects used as keys in a Dictionary object.

ActionScript, unlike many other languages, does not have a way to explicitly remove an object from memory. Instead it waits until all references to an object are removed and then auto-deletes it. Therefore, an object will continue to stay in memory if all strong references aren’t removed.

Below is an example of how strong-references hold an object in memory. If you’d like to try this out, copy the below text into a file called StrongReferencesExample.as

package {
	import flash.display.Sprite;   public class StrongReferencesExample extends Sprite {
		public function StrongReferencesExample() {
			// create a new object called dog. Add it to the first leash object
			// and make leash2 a copy of leash 1.
			var leash1:Object = new Dog();
			var leash2:Object = leash1;   // tracing both leashes will show that they hold a reference to the Dog
			trace(leash1); // [object Dog]
			trace(leash2); // [object Dog]   // deleting the dog from the first leash will not remove it from the second leash
			// even though we originally set leash2 equal to leash1
			leash1 = null;
			trace(leash1); // null
			trace(leash2); // [object Dog]   // The object (dog) will not be free until all of the references to it (leashes) are broken.
			leash2 = null;
			trace(leash1); // null
			trace(leash2); // null
		}
	}
}
// Define a simple Dog class within the same file.
class Dog {}

Richard Lord over at Big Room Games has an interesting article on hacking AS3 to allow you to create weak-references to objects. The hack is pretty decent but lacks a few things I’d like to see like strong typing at compile-time or a more refined ‘memory manager’ type functionality. However, I tried implementing both of these and came up empty handed. If you can think of a way to make this strong-typed, I’ll give you a candy bar.

Using the WeakReference hack could be useful if you want to make sure that an object will not stay in memory if you forget to delete all references to it. However, keeping track of your objects and practicing good memory management is a much better solution and hacks like this one should be saved for special cases where tracking use of an object becomes difficult or impractical.

Thanks to Alex for the link!

分类: Flash 标签: ,