Tom
Tom

Reputation: 8127

Unloading objects for the garbage collector in AS3

I've created an object called loginInterface in flex builder. When this object is initialized it loads the login interface, creating buttons, input boxes and so on.

I created a method for this object called unload. I also have a method which returns whether the interface has been loaded yet. Now, I want to unload the object so that the screen will not only have space for a new interface but the objects should also really be removed so that that memory can be re-allocated.

The loginInterface.as class file:

package
{
    //import required libraries
    import flash.display.Sprite;
    import flash.events.MouseEvent;
    import flash.net.URLRequest;
    import flash.net.navigateToURL;

    public class LoginInterface extends Sprite
    {
        private var welcomeLabel:CustomLabel;
        private var versionLabel:CustomLabel;
        private var loginButton:CustomButton;
        private var registerButton:CustomButton;
        private var usernameLabel:CustomLabel;
        private var passwordLabel:CustomLabel;
        private var usernameInputBox:CustomInputBox;
        private var passwordInputBox:CustomInputBox;
        private var loaded:Boolean = false;

        public function LoginInterface()
        {
            trace("LoginInterface object loaded.");
            init(); //initialize the login interface
        }

        public function init():void //initialize the login interface
        {
            trace("LoginInterface init method was called.");

            //create objects
            welcomeLabel = new CustomLabel(200, 100, 500, 30, "Welcome to the ALPHA client."); //welcome label
            versionLabel = new CustomLabel(200, 120, 500, 30, "Version: v1.0.000", "Arial", 0x000000, 12); //version label
            loginButton = new CustomButton(300, 300, 100, 30, "Login"); //login button
            registerButton = new CustomButton(400, 300, 100, 30, "Register") //register button          
            usernameLabel = new CustomLabel(200, 200, 200, 30, "username: "); //username label      
            passwordLabel = new CustomLabel(200, 240, 200, 30, "password: "); //password label
            usernameInputBox = new CustomInputBox(300, 200, 200, 30, false, 0x6D7B8D); //username input box
            passwordInputBox = new CustomInputBox(300, 240, 200, 30, true, 0x6D7B8D); //password input box

            //add objects to the display tree
            addChild(welcomeLabel);
            addChild(versionLabel);
            addChild(loginButton);
            addChild(registerButton);
            addChild(usernameInputBox);
            addChild(usernameLabel);
            addChild(passwordInputBox);
            addChild(passwordLabel);

            //register object events
            registerButton.addEventListener(MouseEvent.CLICK, registerClicked); //register button is clicked
            loginButton.addEventListener(MouseEvent.CLICK, loginClicked); //login button is clicked

            //interface has been loaded
            loaded = true;
        }

        public function isLoaded():Boolean
        {
            if (loaded) return true;
            return false;
        }

        public function unload():void
        {
            if (!loaded) return;
            //welcomeLabel
            removeChild(welcomeLabel);
            welcomeLabel = null;
            //versionLabel
            removeChild(versionLabel);
            versionLabel = null;
            //loginButton
            loginButton.removeEventListener(MouseEvent.CLICK, loginClicked);
            removeChild(loginButton);
            loginButton = null;
            //registerButton
            registerButton.removeEventListener(MouseEvent.CLICK, registerClicked);
            removeChild(registerButton);
            registerButton = null;
            //usernameInputBox
            removeChild(usernameInputBox);
            usernameInputBox = null;
            //usernameLabel
            removeChild(usernameLabel);
            usernameLabel = null;
            //passwordInputBox
            removeChild(passwordInputBox);
            passwordInputBox = null;
            //passwordLabel
            removeChild(passwordLabel);
            passwordLabel = null;
            //set loaded to false
            loaded = false;
        }

        private function loginClicked(event:MouseEvent):void
        {
            trace("Login button has been clicked.");
            var username:String = usernameInputBox.text;
            var password:String = passwordInputBox.text;
            if (!checkLogin(username, password)) {
                new Alert("Please enter a correct username and password.");
            }
            else {
                trace("Creating socket connection.");
                var socketConnection:SocketConnection = new SocketConnection(this);
            }
        }

        private function checkLogin(username:String, password:String):Boolean
        {
            if ((username == "") || (password == "")) {
                return false;
            }
            return true;
        }

        private function registerClicked(event:MouseEvent):void
        {
            trace("Register button has been clicked.");
            var url:URLRequest = new URLRequest("http://url.com/client/register.php");
            navigateToURL(url, "_blank");
        }
    }
}

Please see the init function where the objects are loaded and the unload function where they should be unloaded. This, visually, works. Is it however the best way to do it - and does it even make these objects unload from memory by the garbage collector after a while?

Upvotes: 2

Views: 2328

Answers (2)

Ross Henderson
Ross Henderson

Reputation: 1779

When you remove an object (such as LoginInterface) from its parent's displayList, all of the children inside of that object will be automatically removed from memory, as well, as long as there are no other objects that contain references to the children.

So, you don't actually need to remove each of the objects you add to LoginInterface's displayList. You just need to remove the event listeners that you assigned.

So, there's nothing wrong with what you've got going, but all you really need in your unload method is:

loginButton.removeEventListener(MouseEvent.CLICK, loginClicked);
registerButton.removeEventListener(MouseEvent.CLICK, registerClicked);

Hope that helps.

Upvotes: 2

John McCann
John McCann

Reputation: 315

You unloading code will work as you intend it to. The Flash garbage collector uses reference counting to determine whether a particular object is a candidate for being garbage collected. After running your unload() function all of the CustomButton objects you created in load() will have a reference count of 0 and will eventually be garbage collected.

Upvotes: 1

Related Questions