ADDED_TO_STAGE event fires twice

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 a 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.

Comments on this post

  1. Lee says:

    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;
    }
    
    • Orland Media says:

      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.

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

      [Download not found]

      Your fix can be made to work fully by us adding the init handler again on removal, and that’s what we’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 we think we have really cracked it, by taking care of business in a superclass. You then override its methods with further code. Let us know what you think about it all anyway and if you spot any problems with this approach.

  2. Orland Media says:

    Adobe report that this bug has been fixed in the latest Flash Player release, but on our testing with player 10.3.181.34 in Firefox 5, it still occurs. We haven’t tried in Beta 11. How about you?

Add a comment:

*