tag:robotlegs.tenderapp.com,2009-10-18:/discussions/problems/515-mediator-doesnt-seem-to-remove-itselfRobotlegs: Discussion 2012-03-19T09:00:10Ztag:robotlegs.tenderapp.com,2009-10-18:Comment/145241782012-03-15T21:51:21Z2012-03-15T21:51:21ZMediator doesn't seem to remove itself<div><p>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???</p>
<p>Kyle</p></div>kamcknigtag:robotlegs.tenderapp.com,2009-10-18:Comment/145241782012-03-15T21:57:01Z2012-03-15T21:57:01ZMediator doesn't seem to remove itself<div><p>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.</p></div>kamcknigtag:robotlegs.tenderapp.com,2009-10-18:Comment/145241782012-03-15T21:59:15Z2012-03-15T21:59:15ZMediator doesn't seem to remove itself<div><p>I have ViewA which contains 16 ViewBs.</p>
<p>App startup<br>
Creative ViewA (it is mediated)<br>
Loop and create 16 ViewBs. (all mediated)<br>
Mediators for ViewBs do something to ViewB</p>
<p>User hits button<br>
ViewA removes all of the old ViewBs (the mediators for these do not
get removed)<br>
Loop and create 16 new ViewBs. (new view and mediators are
created)<br>
Now instead of only the new 16 ViewBs, ALL 32 VeiwBs are still
mediated and responding to events.</p></div>kamcknigtag:robotlegs.tenderapp.com,2009-10-18:Comment/145241782012-03-15T22:28:45Z2012-03-15T22:28:45ZMediator doesn't seem to remove itself<div><p>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).</p>
<p>Could either of those be to blame?</p>
<p>Stray</p></div>Straytag:robotlegs.tenderapp.com,2009-10-18:Comment/145241782012-03-15T22:53:20Z2012-03-15T22:53:20ZMediator doesn't seem to remove itself<div><p>Hmm, nope :/ My mediator for ViewB only has addViewListener and
addContextLitseners, nothing listing to something on any view
children.</p>
<p>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.</p>
<p>The order is<br>
1. Remove old ViewBs from stage (this should trigger the remove of
the mediator but doesnt)<br>
2. Add new ViewBs (new mediators ARE registered)<br>
3. Old mediators still get events<br>
4. New mediators get events<br>
4. Old mediators are unregistered</p>
<p>When I thought it should be:<br>
1. Remove old ViewBs from stage (this should trigger the remove of
the mediator but doesnt)<br>
2. Old mediators are unregistered<br>
3. Add new ViewBs (new mediators ARE registered)<br>
4. New mediators get events</p></div>kamcknigtag:robotlegs.tenderapp.com,2009-10-18:Comment/145241782012-03-16T00:29:54Z2012-03-16T00:29:54ZMediator doesn't seem to remove itself<div><p>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.</p>
<p>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.</p>
<p>Kyle</p></div>kamcknigtag:robotlegs.tenderapp.com,2009-10-18:Comment/145241782012-03-16T00:38:49Z2012-03-16T00:38:49ZMediator doesn't seem to remove itself<div><p>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.</p></div>kamcknigtag:robotlegs.tenderapp.com,2009-10-18:Comment/145241782012-03-16T01:51:57Z2012-03-16T01:51:57ZMediator doesn't seem to remove itself<div><p>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.</p>
<p>I have mapped my view/mediators from innermost first to
outermost being the last mapped.</p></div>kamcknigtag:robotlegs.tenderapp.com,2009-10-18:Comment/145241782012-03-16T07:27:16Z2012-03-16T07:27:16ZMediator doesn't seem to remove itself<div><p>Old mediators persist for one frame after the view is removed -
but only for one frame... and this sounds like more than one
frame?</p>
<p>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.</p>
<p>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!</p>
<p>Stray</p></div>Straytag:robotlegs.tenderapp.com,2009-10-18:Comment/145241782012-03-16T13:34:30Z2012-03-16T13:34:30ZMediator doesn't seem to remove itself<div><p>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! ;)</p>
<p>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.</p></div>kamcknigtag:robotlegs.tenderapp.com,2009-10-18:Comment/145241782012-03-16T13:38:55Z2012-03-16T13:38:55ZMediator doesn't seem to remove itself<div><p>Hey Kyle,</p>
<p>I was just about to post a response.<br>
Just give me 10 minutes to finish it.</p></div>Ondina D.F.tag:robotlegs.tenderapp.com,2009-10-18:Comment/145241782012-03-16T14:24:02Z2012-03-16T15:28:57ZMediator doesn't seem to remove itself<div><p>Hey Kyle,</p>
<p>I’m adding my 2 cents;)</p>
<p>Is it possible that your project is a pure as3 one?<br>
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.</p>
<p>There are 3 buttons: addButton, removeButton, messageButton.<br>
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.</p>
<pre>
<code>
protected function onAddButtonClick(event:MouseEvent=null):void
{
onremoveButtonClick();
for (var i:int=0; i < 3; i++)
{
var view:SomeView=new SomeView();
view.viewName= i + " view " + randomNumber(1, 100);
viewsArray.push(view);
addChild(view);
}
dispatchEvent(new SomeStrangeEvent(SomeStrangeEvent.SEND_SOME_MESSAGE, "dispatched after adding views"));
}
protected function onremoveButtonClick(event:MouseEvent=null):void
{
var arrLength:int=viewsArray.length;
if(arrLength==0)
return;
for (var i:int=0; i < arrLength; i++)
{
trace("[VIEW]ContextView Removing view " + viewsArray[i].viewName);
removeChild(viewsArray[i]);
}
viewsArray=[];
}
protected function onMessageButtonClick(event:MouseEvent=null):void
{
dispatchEvent(new SomeStrangeEvent(SomeStrangeEvent.SEND_SOME_MESSAGE, "dispatched on button click"));
}</code>
</pre>
<p>If you’d trace it, you’d see:<br>
1. Old views get removed from stage<br>
2. New views get added to the display list and their mediators get
created<br>
3. All Mediators(old and new) hear the event<br>
4. Old mediators get removed</p>
<p>In the adding loop the views get added to the display list, and
right after that their mediators get created.<br>
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.</p>
<p>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.<br>
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.</p>
<p>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.</p></div>Ondina D.F.tag:robotlegs.tenderapp.com,2009-10-18:Comment/145241782012-03-16T15:17:11Z2012-03-16T15:17:11ZMediator doesn't seem to remove itself<div><p>It's an AIR app written in AS3 indeed.</p>
<p>Thanks for all the help and info! As always, you guys are
incredibly informative! And that is exactly what seems to be
happening.</p>
<p>Kyle</p></div>kamcknigtag:robotlegs.tenderapp.com,2009-10-18:Comment/145241782012-03-16T20:43:00Z2012-03-16T20:43:00ZMediator doesn't seem to remove itself<div><p>Oh! Good stuff Ondina - thanks for this.</p>
<p>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.</p></div>Straytag:robotlegs.tenderapp.com,2009-10-18:Comment/145241782012-03-16T22:03:20Z2012-03-16T22:03:20ZMediator doesn't seem to remove itself<div><p>I think I read about that while looking for a solution for this
actually! Thanks!</p></div>kamcknigtag:robotlegs.tenderapp.com,2009-10-18:Comment/145241782012-03-19T09:00:10Z2012-03-19T09:00:10ZMediator doesn't seem to remove itself<div><p>@Stray ..and I thank you for the tip on buttonMode. I
didn’t know about it.</p>
<p>@Kyle I’m glad you’re back on track :)</p></div>Ondina D.F.