About Orland MediaDevelopmentTrainingBlogRSS FeedContact us
Microphone

ADDED_TO_STAGE event fires twice

Date: Monday 23rd March 2009
Time: 14:38
Category: ActionScript 3.0
Views: 788
Comments: 2 Comments

Display objects often need to perform set-up tasks which depend on the stage. They might wish to access stage.stageWidth or stage.stageHeight, for example. The trouble is, the stage property will return null until that object is on the Display List.

The standard way around this is to put such set-up tasks in an init method, which you then trigger separately:

private var _box:Box;
_box = new Box();
addChild(_box);
_box.init();

So the init method is triggered once the object is added to the Display List. This works fine. The only downside is that the object cannot initialise itself. This solution seems slightly clumsy from an OOP point of view also a little verbose. Could the object not auto-trigger its own init method once it is on the Display List?

Not until Flash Player 9.0.28.0, which added support for the ADDED_TO_STAGE event, used as follows:

// constructor
public function Box():void
{
   addEventListener(Event.ADDED_TO_STAGE, init);
}

public function init(e:Event):void
{
   // code dependent on stage property
   y = stage.stageHeight-100;
}

The trouble is, however, this event erroneously fires not only for the given item, but also when its parents are added to the Display List. This runs your init method multiple times, possibly causing problems.

This issue is Flash Player bug known to Adobe. Read more about the ADDED_TO_STAGE event firing twice issue in the official bug report entry. A workaround with a sample class may be found there. We use that workaround inherited from a superclass for all our display objects, and until the issue is solved we suggest you either use it too, or use the init method solution when set-up code depends upon the stage.

Social bookmarks
  • Digg
  • Twitter
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • email
  • Reddit
  • StumbleUpon
  • LinkedIn
  • Print
Rate this post
1 star2 stars3 stars4 stars5 stars   (1 votes, average: 5.00 out of 5)

2 Responses to “ADDED_TO_STAGE event fires twice”:

  1. Lee
    April 21st, 2009 at 10:07 pm

    Solved?

    public function init(e:Event):void
    {
      // remove the listener so init will only
      // be called once....
      removeEventListener(Event.ADDED_TO_STAGE, init);
    
      // code dependent on stage property
      y = stage.stageHeight-100;
    }
    

  2. Gavin
    April 22nd, 2009 at 1:08 pm

    Hi Lee,

    Thanks for the comment.

    Yes, that solution does work fine (it’s in Adobe’s bug report), providing you do not remove the item from the Display List then add it again – because then there’s no init handler.

    I’ve had a further look at the issue and put together a few files for testing. I called your fix “Fix 1″ and the other one “Fix 2″. See what you think:

    Download file: ADDED_TO_STAGE Bug Analysis
    (ZIP, 50.68 KB) — Downloaded 5 times

    Your fix can be made to work fully by us adding the init handler again on removal, and that’s what I’ve done in the files. So it looks like this:

    public function SquareInner()
    {
      addEventListener(Event.ADDED_TO_STAGE, init,
      false, 0, true);
      addEventListener(Event.REMOVED_FROM_STAGE, onRemove,
      false, 0, true);
    }
    
    /***************************************************
    Instance methods
    ***************************************************/
    
    private function init(e:Event):void
    {
      // remove handler so it only fires once:
      removeEventListener(Event.ADDED_TO_STAGE, init, false);
      trace(e.target + " was added to the stage");
    }
    
    private function onRemove(e:Event):void
    {
      trace(this + " was removed from stage - adding init
      handler again");
      addEventListener(Event.ADDED_TO_STAGE, init, false,
      0, true);
    }
    

    This method might actually be neater than Fix 2 (it is less verbose).

    We have to be so careful not to leave stray event handlers in AS3 because they can lead to memory leaks. Both of these methods leave the ADDED_TO_STAGE handler in the object while it is off the Display List, but this should not be a problem for GC as it it not repeatedly firing and doesn’t depend on the stage.

    This is quite a fiddly issue. But inside the “Fix 1″ folder, there’s another folder called “With Inheritance”. Here I think I have really cracked it, by taking care of business in a superclass. You then override its methods with further code. Let me know what you think about it all anyway and if you spot any problems with this approach.


Reply

Lenovo Microsoft Adobe Heart Internet Envirowise
Copyright © 2008 Orland Media Ltd | All rights reserved Company details Ethical policy Terms & conditions Privacy policy