12 Replies Latest reply: Apr 16, 2012 8:51 AM by sinious RSS

    removing listeners?

    subtlefly72 Community Member

      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);

      }

        • 1. Re: removing listeners?
          Ned Murphy MVP

          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.

          • 2. Re: removing listeners?
            Mark Jawdoszak Community Member

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

            • 3. Re: removing listeners?
              sinious MVP

              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.

              • 4. Re: removing listeners?
                Mark Jawdoszak Community Member

                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 :-)

                • 5. Re: removing listeners?
                  sinious MVP

                  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.

                  • 6. Re: removing listeners?
                    subtlefly72 Community Member

                    ok so taxbn1 is a button and tax1 is a movieclip.

                    When I put this removed from stage part of the code on my timeline I get this error when moving to the next or previous frame (aavariable is my document class)

                    TypeError: Error #1009: Cannot access a property or method of a null object reference.

                              at aavariable/taxremoved()[aavariable::frame45:27]

                              at flash.display::MovieClip/nextFrame()

                              at aavariable/nextframe()[aavariable::frame1:1387]

                     

                     

                     

                     

                    if I delete this part

                    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);

                    }

                     

                    no errors

                    cheers

                     

                    sub

                    • 7. Re: removing listeners?
                      subtlefly72 Community Member

                      Hey Team !

                      i am still playing around here and removing listeners, I just tried the same idea in a different section and now it is working.. could it be that if I am mistakenly attaching the "removed from stage" listener to something that is not visible it will return an error? 

                      or am I completely wrong?

                      I am not happy that sometimes it works and sometimes it returns an error and I do not know why?!

                       

                      Cheers

                      sub

                      • 8. Re: removing listeners?
                        subtlefly72 Community Member

                        Ok how about this case.. what if I am putting the removed from stage listener on a movieclip and on the next frame there is the same movieclip with a different instance name?

                        Does this count as being removed from the stage?

                        Will this then return an error?

                         

                        Thanks for your patience guys, I think I am getting somewhere

                        One more question, if this is for desktop use, not moble, how much of a deal breaker is it if there are listeners out there that are not turned off? I see someone talking about garbage collection? What is this?

                        cheers

                        sub

                        • 9. Re: removing listeners?
                          Mark Jawdoszak Community Member

                          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 :-)

                          • 10. Re: removing listeners?
                            sinious MVP

                            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.

                            • 11. Re: removing listeners?
                              subtlefly72 Community Member

                              Hey ok I get this, but what if the user doesnt click the buttons? what if they just skip that page and go to the next one?  In this case the listeners have been applied but wont be removed.  (But you are telling me that most times Flash will remove them anyway right?)

                              So.. long story short, if I can manually take the listeners off that 's fine, if I get a case where that is giving me an error and I dont take one or two off then it should still be ok? yes?

                              cheers

                              sub

                              • 12. Re: removing listeners?
                                sinious MVP

                                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.