tag:robotlegs.tenderapp.com,2009-10-18:/discussions/problems/3328-view-mediator-created-destroyed-created-again-and-then-init-called-twiceRobotlegs: Discussion 2013-08-17T10:52:51Ztag:robotlegs.tenderapp.com,2009-10-18:Comment/278162722013-07-17T07:27:23Z2013-07-17T07:28:39ZView Mediator Created, Destroyed, Created Again, and then Init Called Twice<div><p>Hi,</p>
<p>I'm having an issue where a child view is being mediated twice.
I think I've somewhat tracked down the cause, but I don't know how
to solve it.</p>
<p>The child view is just a component in the MXML on the parent
view. The parent view uses multiple states, and I think this is
where I hit trouble. The parent view is placed on stage, and a
mediator is created for the child view. Flex then seems to fire the
event for the parent view's initial state, which seems to cause the
child's views mediator to call destroy(). A new mediator for the
child view is created, and then the initialize function is called
for both the original mediator instance (even though destroy has
already been called) and the new mediator instance. This sets up
all the events twice, causing mayhem.</p>
<p>If I set the mediator's autoRemove setting to false, this
doesn't happen, but that seems like the wrong way to solve this
problem. Any help would be appreciated.</p></div>david.whittinghamtag:robotlegs.tenderapp.com,2009-10-18:Comment/278162722013-07-18T14:27:10Z2013-07-18T14:27:10ZView Mediator Created, Destroyed, Created Again, and then Init Called Twice<div><p>Hi David,</p>
<p>if you had something like this:</p>
<pre>
<code><components:SomeView id="someView" includeIn="firstState, secondState"/></code>
</pre>
<p>then Flex would remove the component from stage before
re-parenting it, as you noticed, and Robotlegs would react as it
should(destroy / create mediators).</p>
<p>The only solution that comes to mind right now is this:</p>
<pre>
<code><components:SomeView id="someView"/></code>
</pre>
<p>Note that I didn't include the includeIn statement! Strangely
enough, Flex won't remove the view when the state changes.</p>
<p>Then when you change the states, if you don't want someView to
be visible in secondState, you change its visibility:</p>
<pre>
<code>if(currentState == "firstState")
{
someView.visible = true;
currentState = "secondState";
}
else
{
someView.visible = false;
currentState = "firstState";
}</code>
</pre>
<p>Or, just don't use states;)</p>
<p>Ondina</p></div>Ondina D.F.tag:robotlegs.tenderapp.com,2009-10-18:Comment/278162722013-07-19T01:09:43Z2013-07-19T01:30:36ZView Mediator Created, Destroyed, Created Again, and then Init Called Twice<div><p>Hi Ondina, thanks for replying.</p>
<p>The thing is, I'm not using the <em>includeIn</em> attribute on
the child view. However, it's parent container does get
enabled/disabled with state changes.</p>
<p>My issue isn't so much that the mediator gets created/destroyed
with state changes, its that <em>initialize</em> is called on the
child view after <em>destroy</em> is called..</p>
<p>Edit: Furthermore, I just tried out your advice of not using
states, and it's still being mediated twice, exactly the same as
before with <em>initialize</em> being called after
<em>destroy</em>.</p></div>david.whittinghamtag:robotlegs.tenderapp.com,2009-10-18:Comment/278162722013-07-19T07:27:14Z2013-07-19T07:27:14ZView Mediator Created, Destroyed, Created Again, and then Init Called Twice<div><p>Hey David,</p>
<p>Are you using any other libraries/plugins/utilities - Starling,
tweening, effects, e.t.c.?<br>
How are you adding your child view to its parent, through
actionscript or in mxml?</p>
<blockquote>
<p>My issue isn't so much that the mediator gets created/destroyed
with state changes, its that initialize is called on the child view
after destroy is called.</p>
</blockquote>
<p>But if initialize is called, it means that a new mediator is
created for the re-parented view.<br>
Add handlers in your child view for the ADDED_TO_STAGE and
REMOVED_FROM_STAGE events to see what happens when the state
changes.</p>
<p>Could you attach the project or a stripped down version that
replicates the issue?<br>
Or paste all relevant code ( for the parent and child mediators +
views)?</p></div>Ondina D.F.tag:robotlegs.tenderapp.com,2009-10-18:Comment/278162722013-07-19T07:58:32Z2013-07-19T07:58:32ZView Mediator Created, Destroyed, Created Again, and then Init Called Twice<div><blockquote>
<p>then the initialize function is called for both the original
mediator instance (even though destroy has already been called) and
the new mediator<br>
instance.</p>
</blockquote>
<p>If that's the case then something's definitely wrong. As Ondina
said, could<br>
you provide a bare bones version which exhibits this behaviour?</p></div>creynderstag:robotlegs.tenderapp.com,2009-10-18:Comment/278162722013-07-19T12:46:15Z2013-07-19T12:46:15ZView Mediator Created, Destroyed, Created Again, and then Init Called Twice<div><blockquote>
<p>Furthermore, I just tried out your advice of not using states,
and it's still being mediated twice, exactly the same as before
with initialize being called after destroy.</p>
</blockquote>
<p>Now I think that your mediator is not getting destroyed at all,
actually.<br>
You'd have to use the Profiler to verify that.</p>
<p>Usually, a mediator can't be destroyed if it holds a reference
to its view in a way or another.</p>
<p>Are you, by any chance, listening for events from view like this
(which is not a good practice in my opinion) :</p>
<pre>
<code>view.someButton.addEventListener(MouseEvent.CLICK, onSomethingHappened);</code>
</pre>
<p>If you do, you have to remove the event listener manually in
your destroy() method. Robotlegs removes only the event listeners
added via addContextListener and addViewListener when destroy() is
running.</p></div>Ondina D.F.tag:robotlegs.tenderapp.com,2009-10-18:Comment/278162722013-07-22T02:24:35Z2013-07-22T02:25:57ZView Mediator Created, Destroyed, Created Again, and then Init Called Twice<div><p>Back in the office after the weekend.</p>
<blockquote>
<p>Are you using any other libraries/plugins/utilities - Starling,
tweening, effects, e.t.c.?</p>
</blockquote>
<p>I load the the default bundle. I am using the Robotlegs State
Machine utility, but not within the plug-in architecture of
RL2.0+.</p>
<blockquote>
<p>How are you adding your child view to its parent, through
actionscript or in mxml?</p>
</blockquote>
<p>MXML</p>
<blockquote>
<p>Could you attach the project or a stripped down version that
replicates the issue? Or paste all relevant code ( for the parent
and child mediators + views)?</p>
</blockquote>
<p>I can possibly do that. The project is actually a plug-in for a
third-party closed-source application, so I will have to re-work a
few things to build up a test case that can exist separately from
that environment. The third-party app just loads the plugin as a
Flex module, so I there isn't too much to do. I'll do my best to
get around to this soon.</p>
<blockquote>
<p>Are you, by any chance, listening for events from view like this
(which is not a good practice in my opinion)</p>
<p><code>view.someButton.addEventListener(MouseEvent.CLICK,
onSomethingHappened);</code></p>
</blockquote>
<p>I'm not, I would also consider this bad practice. All
interaction between the view and the mediator is through normal
function calls exposed on an interface for the view. In the
mediator, the only listeners I setup are via addContextListener and
addViewListener. The only reference to the view is injected in, via
matching the view's interface to the mediator in the mediator
map.</p></div>david.whittingham