Mediator doesn't seem to remove itself
Hey everyone, I have a view that is mediated, and the mediator registers just fine when the view is added to the stage. But I'm running into memory leaks where it appears that old views and mediators are remaining in memory and still being mediated. I'm pretty sure I've removed all references, and when you remove the view from the stage it should automatically remove the mediator correct? But when I override the onRemove in the mediator to put a trace, that trace never gets called. I did notice that in my view I have added listener for the Event.REMOVED_FROM_STAGE and added some cleanup in there. It appears that if i remove that listener, then the mediator gets removed (though it seems to do it later than it should bsased on some other traces). Is there a reasono that having that listener on my view would mess that up???
Kyle
Comments are currently closed for this discussion. You can start a new one.
Keyboard shortcuts
Generic
? | Show this help |
---|---|
ESC | Blurs the current field |
Comment Form
r | Focus the comment reply box |
---|---|
^ + ↩ | Submit the comment |
You can use Command ⌘
instead of Control ^
on Mac
1 Posted by kamcknig on 15 Mar, 2012 09:57 PM
OK, so it's not my adding the listener that is the problem. It' something that I'm doing in there that is causing this error. BUT, this should not be occuring at all since the function in question shouldn't be called since by the time it would be, the mediator for this old view should have been removed.
2 Posted by kamcknig on 15 Mar, 2012 09:59 PM
I have ViewA which contains 16 ViewBs.
App startup
Creative ViewA (it is mediated)
Loop and create 16 ViewBs. (all mediated)
Mediators for ViewBs do something to ViewB
User hits button
ViewA removes all of the old ViewBs (the mediators for these do not get removed)
Loop and create 16 new ViewBs. (new view and mediators are created)
Now instead of only the new 16 ViewBs, ALL 32 VeiwBs are still mediated and responding to events.
3 Posted by Stray on 15 Mar, 2012 10:28 PM
Hi there, usually this problem is caused by adding listeners to views directly, instead of via the event map (or listening to signals directly, instead of through the signal map).
Could either of those be to blame?
Stray
4 Posted by kamcknig on 15 Mar, 2012 10:53 PM
Hmm, nope :/ My mediator for ViewB only has addViewListener and addContextLitseners, nothing listing to something on any view children.
I've also noticed that when it DOES remove mediators (if i remove my clean up that causes a null error later on), it doesnt seem to do it when it should.
The order is
1. Remove old ViewBs from stage (this should trigger the remove of the mediator but doesnt)
2. Add new ViewBs (new mediators ARE registered)
3. Old mediators still get events
4. New mediators get events
4. Old mediators are unregistered
When I thought it should be:
1. Remove old ViewBs from stage (this should trigger the remove of the mediator but doesnt)
2. Old mediators are unregistered
3. Add new ViewBs (new mediators ARE registered)
4. New mediators get events
5 Posted by kamcknig on 16 Mar, 2012 12:29 AM
OK. I "think" it might have to do with the face that ViewA was injected into ParentView. And ParentVIew was mapped as a singleton. So a new ViewA was not being created each time. So I think ViewA's mediator was actually the problem, and not the child views, ViewB.
The project is so big at this point it's hard to tell what actually caused it. But mapping ParentVIew using mapClass instead of mapSingleton "seems' to have fixed it.
Kyle
6 Posted by kamcknig on 16 Mar, 2012 12:38 AM
OK. shoot. maybe not. that seemed to have fixed one problem, but I've still got the same problem in another use case with the same items.
7 Posted by kamcknig on 16 Mar, 2012 01:51 AM
OK, another update. I'm about 99% sure that my problem seems to be the order in which things are unregistered. It seems that the ViewBs are removed from stage, then other views are added and their mediators registered, then some system events get fired for those and get handled by not only the new ones but the old ones that are still in the system... and THEN the old one's mediators get removed.
I have mapped my view/mediators from innermost first to outermost being the last mapped.
8 Posted by Stray on 16 Mar, 2012 07:27 AM
Old mediators persist for one frame after the view is removed - but only for one frame... and this sounds like more than one frame?
If it's just one frame (we do that because of some sneaky reparenting that v3 flex components do behind your back) then the fix is to check the .stage property of your view and bail from any handler if it's null.
But... it sounds like it's something else. If you want to post some code, that might make it easier to chase up. I'm going away now but there are many other keen and clever people here to help!
Stray
9 Posted by kamcknig on 16 Mar, 2012 01:34 PM
OK, thanks! I actually did start checking for stage in this instacne as my own solution before you posted, I had thought that might be super hacky but if you say it's ok! ;)
I'll leave this open for another day or two just in case someone else has other solutions. It'll be hard to post some code but if I can break it down and still get the problem to appear I'll post some.
Support Staff 10 Posted by Ondina D.F. on 16 Mar, 2012 01:38 PM
Hey Kyle,
I was just about to post a response.
Just give me 10 minutes to finish it.
Support Staff 11 Posted by Ondina D.F. on 16 Mar, 2012 02:24 PM
Hey Kyle,
I’m adding my 2 cents;)
Is it possible that your project is a pure as3 one?
Please excuse the silly example I’ll use bellow. It’s just easier for me to explain what I think is the cause of your problem.
There are 3 buttons: addButton, removeButton, messageButton.
On addButtonClick I’m adding views in a ‘for’ loop, and right after that I’m dispatching SomeStrangeEvent, that will be heard by the new mediators for the new views, but also by the old ones. As you can see bellow, before adding new views, the old ones get removed.
If you’d trace it, you’d see:
1. Old views get removed from stage
2. New views get added to the display list and their mediators get created
3. All Mediators(old and new) hear the event
4. Old mediators get removed
In the adding loop the views get added to the display list, and right after that their mediators get created.
We would expect that in the remove loop the views get removed from stage, and right after that their mediators get removed as well. But that’s not what’s happening.
So if you remove and add views in a loop, you have to make sure that all old views have been removed from stage before dispatching an event.
If you’d comment out the line where the event gets dispatched and instead you’d click the messageButton after removing/adding your views, you’d see that everything worked fine.
Another issue with pure as3 projects could be that the Event.ADDED_TO_STAGE fires twice under certain circumstances. It’s an old bug, and I don’t know if it has been fixed in the newest player. Maybe that’s not related to your problem, though I wanted to let you know about it.
12 Posted by kamcknig on 16 Mar, 2012 03:17 PM
It's an AIR app written in AS3 indeed.
Thanks for all the help and info! As always, you guys are incredibly informative! And that is exactly what seems to be happening.
Kyle
kamcknig closed this discussion on 16 Mar, 2012 03:17 PM.
Stray re-opened this discussion on 16 Mar, 2012 08:43 PM
13 Posted by Stray on 16 Mar, 2012 08:43 PM
Oh! Good stuff Ondina - thanks for this.
One more as3 bug to add to the mix - setting buttonMode to true prevents a sprite from being Garbage Collected - so it's worth setting buttonMode back to false on any sprites before dropping references to them. An alternative is a self-referential ADDED listener inside the sprite that toggles buttonMode internally as the view comes and goes.
14 Posted by kamcknig on 16 Mar, 2012 10:03 PM
I think I read about that while looking for a solution for this actually! Thanks!
Support Staff 15 Posted by Ondina D.F. on 19 Mar, 2012 09:00 AM
@Stray ..and I thank you for the tip on buttonMode. I didn’t know about it.
@Kyle I’m glad you’re back on track :)
Ondina D.F. closed this discussion on 19 Mar, 2012 09:00 AM.