views:

885

answers:

2

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?

+1  A: 

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.

John McCann
+2  A: 

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.

Ross Henderson
The LoginInterface object has been added to the displayList of it's parent. I need to unload the interface in another child of the logininterface object however. I don't think that's possible? So I need to do it the way I'm doing it now, or not?
Tom
@rhtx. Removing the listeners in this case is good idea (and good practice in general), but it's not strictly necessary for making LoginInterface eligible for GC.
Juan Pablo Califano