Skip navigation
Currently Being Moderated

removing listeners?

Apr 4, 2012 4:03 AM

Hi team,

Is it always best practice to remove every listener that you create in a project?

I thought I had this worked out but all of a sudden I am getting errors by trying to use the removed from stage listener.

So there are buttons on the stage and some movieclips that those buttons make visible and here is the code that I am trying to use, but it generates errors on leaving the frame.  I think this is the same as what I have been using but somehow it is now not working for me.

Any help greatly appreciated

cheers

sub

taxb1.visible=false;

taxb2.visible=false;

taxb3.visible=false;

taxb4.visible=false;

 

 

taxbn1.addEventListener(MouseEvent.CLICK, taxb1go);

function taxb1go(e:MouseEvent){

          taxb1.visible=true;

}

taxbn2.addEventListener(MouseEvent.CLICK, taxb2go);

function taxb2go(e:MouseEvent){

          taxb2.visible=true;

}

taxbn3.addEventListener(MouseEvent.CLICK, taxb3go);

function taxb3go(e:MouseEvent){

          taxb3.visible=true;

}

taxbn4.addEventListener(MouseEvent.CLICK, taxb4go);

function taxb4go(e:MouseEvent){

          taxb4.visible=true;

}

taxbn4.addEventListener(Event.REMOVED_FROM_STAGE, taxremoved);

function taxremoved(e:Event){

          taxbn1.removeEventListener(MouseEvent.CLICK, taxb1go);

          taxbn2.removeEventListener(MouseEvent.CLICK, taxb2go);

          taxbn3.removeEventListener(MouseEvent.CLICK, taxb3go);

          taxbn4.removeEventListener(MouseEvent.CLICK, taxb4go);

          taxbn4.removeEventListener(Event.REMOVED_FROM_STAGE, taxremoved);

}

 
Replies
  • Currently Being Moderated
    Apr 4, 2012 4:38 AM   in reply to subtlefly72

    I don't readily see any problem with the code as you show it.  You should include the error messages you are getting.  You could plant traces to see if your taxremoved function ever gets called.

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 4, 2012 4:58 AM   in reply to subtlefly72

    What errors are you receiving?

    You have some references to taxb4 and taxbn4 (with an "n") are those the same thing and it's just a case of pasting here?  Or is that something else entirely?

     

    You could always try:

    if( taxbn1.hasEventListener( MouseEvent.CLICK ) )

    {

    taxbn1.removeEventListener( MouseEvent.CLICK, taxb1go );

    }

     

    You'll obviously have to create an if statement for each event, but at least it would catch them (if they exist).

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 4, 2012 7:27 AM   in reply to Mark Jawdoszak

    On devices, for the same of RAM and CPU you always want to remove it as SOON as you don't need it. Otherwise you can use garbage collection.

     

    The weak reference argument when adding a listener tells flash it's ok to discard the listener once Flash knows it doesn't need it. If your button is no longer on the display list (e.g. you move to a frame that it doesn't exist on the timeline in) that listener will be marked to removal if the system does a garbage collection.

     

    Here's a weak reference example:

    taxbn4.addEventListener(Event.REMOVED_FROM_STAGE, taxremoved, false, 0, true);

     

    The true tells flash "it's ok to dump this listener if the object it's assigned to no longer exists".

     

    Again, it's good practice to remove listeners, especially on mobile, but on desktop you can do this and not need to worry about it if you use the timeline a lot to place your objects.

     

    If you instantiate your visual objects in code, (e.g. var mySprite:SomeLibraryClip = new SomeLibraryClip();), and you do that in a global context (e.g. on a timeline), then this approach does not work. mySprite will contain a reference in memory to the clip even after you take it off the display list and the listener will never be marked for removal.

     

    I'm assuming you're just using the timeline though.

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 4, 2012 7:27 AM   in reply to sinious

    I've always gotten into the habit of removing listeners when not needed - and using a clean-up routine to check the hasEventListener.

     

    BUT, I really like that weak reference!  (Didn't even know it existed... I guess because of forcing myself to clean-up after every listener).  Thanks for that :-)

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 4, 2012 7:37 AM   in reply to Mark Jawdoszak

    I'm a coder not a designer. I get designs and code flash to make whatever the designers need work. I don't get to use the weak reference approach myself because I create everything in code but I apply it to every listener when I'm developing for mobile. I do it as a "just incase my removal of the listener fails" or something weird as over the years flash has done some really odd things (especially actionscript 2.0).

     

    Weak reference won't fail on you out of the blue, don't worry about that. As long as your button remains on screen the listener will never be garbage collected (removed). But for desktop, I use that all the time because RAM and CPU are in abundance.

     

    To answer your OP, I see no issue with your code. Checking for the listener is a good idea but you can see how that starts to ramp up code with gobs of extra code just to be safe. Weak reference is the lazy mans way, but it works just fine. Profile in flash builder and you'll see it indeed works just fine. Push the garbage collection button and you'll see the reference disappear.

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 5, 2012 12:25 AM   in reply to subtlefly72

    Are you attaching the event listener to the movie clip manually, or is it part of a class that extends MovieClip?  If the event is within some code that extends MovieClip, then both will have the listener.  But, if you are attaching the listener to the movie clip instance that you created, and you are doing so manually, then no, the second clip won't have the listener.

     

    AS3 (like Java and C#) are Garbage Collected languages.  This means that whenever an object goes out of scope, it is automagically cleaned up, removed from RAM and that space is made available.

    So, if you have a MovieClip that you have now done a removeChild() on, so it is no longer on stage and not being used, then chances are the next time the GC is run, it will be wiped.  (so long as no other references to it exist).

    However, if you have ANY event listeners bound to ANY objects, then those objects CANNOT be Garbage Collected.

     

    Let's say we have a MovieClip, and in that we have an instance of FLVPlayback component... then in there we load a large, HD video file, attach the listeners and play it.  We could be taking, I dunno, 100MB RAM with the video (it's a nice round number - would probably be lower, though).  If we're done with the video and we remove the component from the stage but never remove the event listeners, then all that RAM can never be Garbage Collected - thus, we have a reasonably large impact on system RAM.  Now if this little app can open and stream many different HD videos and none of them are probably GC'd, then we can pretty quickly run out of system RAM.

    This problem is exponentially more prominent when we shift it to Mobile devices, as RAM usage (and the application sandbox limitations) are much lower!


    Hope that helps :-)

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 5, 2012 6:51 AM   in reply to subtlefly72

    I don't know what your timeline looks like but I'm assuming you're using it heavily for this.

     

    Gawd you're going to make me go to photoshop. Lets make this real easy and get a picture in here........

     

    Here's an example of not being able to assign a new instance name over 2 frames:

    http://www.filehorde.com/o/nokeyframes.jpg

     

    In the above picture the object extends 2 frames. If you clicked on that second frame and changed the instance name, it would change it for frame 1 as well.

     

    Here's 2 keyframes, and an example of where you could set 2 separate instance names:

    http://www.filehorde.com/o/keyframes.jpg

    In the above picture you are making 2 separate instances so therefore you can give each one a different instance name.

     

    That out of the way......

     

    Using the second image example because this is what I assume you are doing, when you go from frame 1 to 2, all your listeners assigned on frame 1 are gone. They will be garbage collected. You do not need to remove them yourself. However if you are programming for a mobile device then it's a good idea to remove them manually anyway to free up ram instantly.

     

    Flash does a lot of things automagically for you. Removing your listeners when you change frames in the second picture is one of them. Setting a weak reference further reinforces that flash is making the right decision to clean up the listeners automatically in garbage collection for you.

     

    Now..

     

    If you REALLY want to remove them yourself, then remove them in the buttons MouseEvent.CLICK method rather than REMOVED_FROM_STAGE. It makes sense and it will always work.

     

    e.g.

     

    btn1.addEventListener(MouseEvent.CLICK, btnHandler, false, 0, true);

     

    function btnHandler(e:MouseEvent):void

    {

         btn1.removeEventListener(MouseEvent.CLICK, btnHandler);  // don't put the extra false, 0, true here or it will error

         gotoAndStop(2);

    }

     

    You get the general idea.. remove 1 - 99999 listeners or whatever you want to do in the CLICK handler, then do what you want the button to do, like move to another frame. You don't need to worry about removing things you have on the timeline from the display list via code. If you use the timeline, the timeline will do that for you.

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 16, 2012 8:51 AM   in reply to subtlefly72

    Sorry for the late reply. Flash is good at cleaning garbage but it will be a lot better if you, so to speak, give it permission. If you use the weakReference parameter of assigning a listener then you give flash explicit permission to remove the listener once there are no more "references" to the object it is told to listen for.

     

    For a real quick and dirty intro, garbage collection is about "valid references". A reference is something in memory pointing to something that exists. Once you instantiate an object inside a function it has a reference count of 1 until the function ends. If you assigned the object created to a "class" or "global" variable, that reference will remain intact at 1 even after the function ends. If you remove it from the display list it will continue to exist because you assigned it to a class or global level variable.

     

    However.

     

    If you use the timeline exclusively, flash treats this differently. If you place an object in a frame, flash auto-adds 1 to it, or sets it reference count at 1. Stay with me here.. Once you go to another frame that DOES NOT have that object on it, flash automatically subtracts 1 reference count to that object.

     

    Any objects with a reference count of 0, or nothing "refers" to it, will be cleaned automatically from flash via what is called "garbage collection". Garbage collections purpose is to remove anything with a reference count of 0.

     

    I know that's a lot to chew on but counting references is how garbage collection works. If you add a listener to an object that is considered a reference. So when you have it on the timeline and also add a listener to it, the reference count is 2. So even when you go off the frame and the object is no longer on the timeline its reference count is subtracted by 1. But because you added a listener, it went instead from 1 to 0, it went from 2 to 1. Therefore, it still exists and is taking up memory.

     

    You use weakReference to combat this issue. We're talking about realtime resources here. Even if you don't use weakReference it will EVENTUALLY be cleaned up, but when using devices you should clean reference counts as soon as possible. By simply specifying weakReference to true as soon as you move off the frame, regardless that you added 1 to its reference count by adding a listener, flash regards it as basically only having a reference count of 1 instead of 2. So it will be cleaned up "automagically" for you.

     

    Learning to manage references to objects are king to the device programming world. I'm sure this can be explained better but feel free to ask any questions about what I said and what doesn't make sense if you have any.

     
    |
    Mark as:

More Like This

  • Retrieving data ...

Bookmarked By (0)

Answers + Points = Status

  • 10 points awarded for Correct Answers
  • 5 points awarded for Helpful Answers
  • 10,000+ points
  • 1,001-10,000 points
  • 501-1,000 points
  • 5-500 points