tag:robotlegs.tenderapp.com,2009-10-18:/discussions/problems/644-events-being-caught-intermittentlyRobotlegs: Discussion 2012-09-21T14:12:45Ztag:robotlegs.tenderapp.com,2009-10-18:Comment/188214432012-09-18T07:14:53Z2012-09-18T07:14:53ZEvents being caught intermittently <div><p>Hi John,</p>
<p>What kind of a component is the child of the View? Is it, by any
chance, a List or a DataGrid using an ItemRenderer? ItemRenderers
are known for their <em>unpredictable</em> behavior. That’s
correct, you should let the event bubble and override clone. But
instead of listening directly on an ItemRenderer in the Mediator,
the View, the parent component of the List or DataGrid, should
handle the event dispatched by its child and then re-dispatch a
custom event (with a payload) to its Mediator.</p>
<p>Is the parent component able to hear the event every time the
subcomponent dispatches it? If the answer is no, then the issue
you’re encountering has nothing to do with robotlegs.</p>
<p>Are you keeping a reference to the context?<br>
<a href=
"http://knowledge.robotlegs.org/kb/reference-mvcs-implementation/keep-a-reference-to-your-context-or-it-will-be-garbage-collected">
http://knowledge.robotlegs.org/kb/reference-mvcs-implementation/kee...</a></p>
<p>If this doesn’t answer your question, is it possible to
post some code or attach a simple application reproducing the
issue?</p>
<p>Cheers,<br>
Ondina</p></div>Ondina D.F.tag:robotlegs.tenderapp.com,2009-10-18:Comment/188214432012-09-18T14:32:47Z2012-09-19T17:53:25ZEvents being caught intermittently <div><p>Hi Ondina,</p>
<p>Thanks for the response. This is an AS3 project. The child of
the view is a class that extends flash.display.Sprite.</p>
<p>Yes, the parent is able to hear the event each time the
subcomponent dispatches it.</p>
<p>Yes, I'm keeping a reference to the context.</p>
<p>The code involved seems to be basics...<br>
I use mediatorMap.mapView to map the view to the mediator<br>
The mediator uses addViewListener to listen for the event<br>
contextView.addChild to add the view to the main context<br>
The child dispatches the event, bubbling true<br>
The event passes its parent and is caught by the mediator
(sometimes)</p>
<p>I'm using the robotlegs swc. Maybe I should download the source
and attempt to step through.</p>
<p>Regards,<br>
John</p></div>John R. Nyquisttag:robotlegs.tenderapp.com,2009-10-18:Comment/188214432012-09-18T15:05:53Z2012-09-18T15:05:53ZEvents being caught intermittently <div><p>Hey John,</p>
<p>If you’re going to link against the source, you should
know about this (maybe you already do):</p>
<p><a href=
"https://github.com/robotlegs/robotlegs-framework/wiki/Common-Problems#wiki-metadata-stripping">
https://github.com/robotlegs/robotlegs-framework/wiki/Common-Proble...</a></p>
<blockquote>
<p>The mediator uses addViewListener to listen for the event
contextView.addChild to add the view to the main context</p>
</blockquote>
<p>Not sure what you mean. It sounds a bit unusual.</p>
<p>Can you post at least the code where you are mapping the event
listener inside your mediator, and where you’re dispatching
the event from the view? Is the event dispatched from the child
component triggered by user interactions or something else? What's
going on inside your sub-component?<br>
If you try to let the parent listen for the child’s event and
then redispatch it within an event handler, can the mediator catch
it?</p>
<p>Without seeing some code it’s really hard to guess
what’s going on in your app, but I think the issue has
something to do with the way you are mapping the event or with some
additional logic you have in your mediator’s onRegister() ,
or with the component itself.<br>
I’m pretty sure it’s not robotlegs’ fault ;)</p>
<p>Ondina</p></div>Ondina D.F.tag:robotlegs.tenderapp.com,2009-10-18:Comment/188214432012-09-18T15:47:23Z2012-09-18T15:47:48ZEvents being caught intermittently <div><p>Here, an example of a ParentViewMediator listening for a custom
event, dispatched by ParentView within an event handler for an
event dispatched by its ChildView.</p>
<p>ParentView:</p>
<pre>
<code>private function init():void
{
var childView:ChildView = new ChildView();
addChild(childView);
childView.addEventListener(IndexChangeEvent.CHANGE, childViewEventHandler);
}
private function childViewEventHandler(event:IndexChangeEvent):void
{
//someData = event.currentTarget.selectedItem
dispatchEvent(new SomeEvent(SomeEvent.SOMETHING_HAPPEND_WITHIN_THE_CHILDVIEW, someData));
}</code>
</pre>
<p>ParentViewMediator:</p>
<pre>
<code>override public function onRegister():void
{
addViewListener(SomeEvent.SOMETHING_HAPPEND_WITHIN_THE_CHILDVIEW, onSomethingHappened, SomeEvent);
}</code>
</pre></div>Ondina D.F.tag:robotlegs.tenderapp.com,2009-10-18:Comment/188214432012-09-18T16:27:55Z2012-09-19T17:53:25ZEvents being caught intermittently <div><p>Thanks for the link. When I mentioned using the source to step
through, I did not intend to imply it might be robotleg's fault.
I'm new to robotlegs and I thought stepping through might give me
insight into where I may be confusing the framework.</p>
<p>Regarding code...<br>
In the child of the view:</p>
<pre>
<code> private function statusHandler(event : NetStatusEvent) : void {
switch (event.info.code) {
case "NetStream.Play.Stop":
dispatchEvent(new VideoEvent(VideoEvent.VIDEO_ENDED, true));
break;
}
}</code>
</pre>
<p>In the mediator:</p>
<pre>
<code> override public function onRegister() : void {
addViewListener(VideoEvent.VIDEO_ENDED, onVideoEnded, VideoEvent);
}
private function onVideoEnded(e:VideoEvent):void
{
//turn view event to application event
dispatch(new DecisionEvent(DecisionEvent.SHOW_ACTIONS) );
}</code>
</pre></div>John R. Nyquisttag:robotlegs.tenderapp.com,2009-10-18:Comment/188214432012-09-18T17:05:20Z2012-09-18T17:05:20ZEvents being caught intermittently <div><blockquote>
<p>When I mentioned using the source to step through, I did not
intend to imply it might be robotleg's fault.</p>
</blockquote>
<p>Hehe, ok.</p>
<p>Is your child view always on stage, or are you removing it after
it has dispatched an event?</p></div>Ondina D.F.tag:robotlegs.tenderapp.com,2009-10-18:Comment/188214432012-09-18T17:44:22Z2012-09-18T17:44:22ZEvents being caught intermittently <div><p>The code you posted looks ok, but it’s really better to
let the parent view handle the child’s event and re-dispatch
it as I showed you in a previous post. I'm out of time for today,
it’s evening here, where I live, so I can’t get into
more details...</p>
<p>All I can think of right now are some components re-parenting
issues ( ‘The mediator uses addViewListener to listen for the
event contextView.addChild to add the view to the main
context’ ), changing states, asynchronous
processes…<br>
If you want, you can attach your app. I’m willing to take a
look at it. I can make the discussion private, download the code,
delete the attachment, and mark it as public again, if, for some
reason, you want to hide it from the public eye. Btw, you can mark
it as private as well.<br>
I’ll be back tomorrow with more answers, hopefully. Maybe
others will have more suggestions too.</p></div>Ondina D.F.tag:robotlegs.tenderapp.com,2009-10-18:Comment/188214432012-09-18T22:48:49Z2012-09-19T17:53:26ZEvents being caught intermittently <div><p>Thanks for your help, Ondina, have a good evening. I'll go ahead
an turn bubbling off, have the parent view catch it, and then
re-dispatch it and see how that goes.</p></div>John R. Nyquisttag:robotlegs.tenderapp.com,2009-10-18:Comment/188214432012-09-19T14:13:54Z2012-09-19T17:09:14ZEvents being caught intermittently <div><p>You’re welcome, John. Hopefully, we’ll find out what
exactly is causing the issue you have faced.<br>
Sometimes it’s hard to know the knowledge level of newcomers
to the framework, so, perhaps, some of the things I’m going
to mention further down won’t be new to you or won’t
apply to your use case or type of project (pure as3), but they may
help others in the future.</p>
<p><strong>#</strong> general rule: make sure that the event is not
dispatched before you actually listen to it</p>
<p><strong>=</strong> check whether you are keeping a reference to
the context</p>
<p><strong>=</strong> check whether a Mediator is able to receive
events</p>
<p>Creation of Mediators (from Best Practices)<br>
„When a view component class is mapped for mediation, you can
specify if you would like to have the Mediator for the class
created automatically. When this option is true the context will
listen for the view component instance to dispatch its
ADDED_TO_STAGE event. When this event is received, the view
component will be automatically mediated and its mediator can begin
to send and receive framework events“</p>
<p>“It is common to add event listeners in the onRegister
method of the Mediator. At this phase of the Mediator’s
lifecycle, it has been registered and its view component and other
dependencies have been injected.“</p>
<p>If the view is already on stage before the mediator is mapped
(mediatorMap.mapView) the mediator won’t be created
automatically.<br>
(with the exception of the ContextView)</p>
<p><strong>=</strong> check whether it’s the same instance of
a Mediator that is supposed to respond to an event. When Views get
removed from stage, their Mediators get removed as well, when
autoRemove is true (the default value of
mediatorMap.mapView’s last argument).</p>
<p><strong>=</strong> check the syntax of addViewListener or
eventMap.mapListener</p>
<p><strong>=</strong> make sure you’re listening for the
right event</p>
<p><strong>=</strong> check whether the Event class overrides
clone()</p>
<p><strong>=</strong> check whether the event bubbles, in case
it’s being dispatched by subcomponents of the mediated
view</p>
<p><strong>=</strong> check whether there are event names
collisions</p>
<p><strong>=</strong> is there some additional logic in the
onRegister() of the Mediator, besides the registration of event
listeners, that could affect the way the Mediator listens for
events? Service calls?</p>
<p><strong>=</strong> adding listeners to views directly can keep
the mediators from being removed</p>
<p><strong>=</strong> View specific</p>
<ul>
<li>components life cycle (construction, addition, initialization,
invalidation, validation, updating and removal) with impact on the
order of events execution or ability to listen to them</li>
<li>ItemRenderers – recycling issues</li>
<li>Resizing, Effects, Transitions, States – re-parenting
issues</li>
<li>Race conditions:</li>
</ul>
<p>-- asynchronicity issues: network calls, streaming affecting the
order of execution of other parts in your code. Network requests
don't block the UI.</p>
<p>-- concurrency issues: check if event listeners finish executing
before the next listener is called. - data providers’ data
change events, collections’ change notifications –
updating and refreshing issues</p>
<ul>
<li>removing and adding views in a loop can cause all Mediators
(old and new) to hear the event</li>
<li>another issue with pure as3 projects could be that the
Event.ADDED_TO_STAGE fires twice under certain circumstances
(possible bug)</li>
<li>other FP bugs ….</li>
</ul>
<p>I'm sure this list is not exhaustive.</p>
<p>Try to build a very simple application for learning purposes. No
network calls, no videos and so on. See if a custom event from a
simple child view is reaching parent view’s mediator. If it
does, then you can add gradually more logic to your child view and
see how it behaves. Also, investigate the way you’re adding
and removing views from stage and how the framework reacts to it.
Next, you can see if the VideoPlayer is causing some trouble.</p>
<p>Let us know of your progress.</p>
<p>Ondina</p></div>Ondina D.F.tag:robotlegs.tenderapp.com,2009-10-18:Comment/188214432012-09-19T17:12:50Z2012-09-19T17:53:26ZEvents being caught intermittently <div><p>That's a great list. I'm not new to AS3, but I am to RL, so it
good to have some of these points re-enforced. I did start it with
a simple example and grew it in complexity, I've been trying to
mirror my structure with the structure of some examples where
possible. My project is working consistently now. I am no longer
bubbling the event, I have the parent re-dispatch. I've used event
bubbling in AS3 for 5 years without an issue. You mentioned
"it’s really better to let the parent view handle the
child’s event and re-dispatch", is this an aspect of RL or do
you feel it is true in general? I realize it is probably better for
performance not to bubble, and it also is more explicit in your as
to what you are listening/catching, those are good things :) But
are there other reasons either RL-related or not that you chose to
forgo that mechanism?</p>
<p>Thank you for all the help and insights, Ondina!</p></div>John R. Nyquisttag:robotlegs.tenderapp.com,2009-10-18:Comment/188214432012-09-20T13:24:54Z2012-09-21T14:12:45ZEvents being caught intermittently <div><p>Glad you liked my list. Thank you :)</p>
<blockquote>
<p>I realize it is probably better for performance not to bubble,
and it also is more explicit in your as to what you are
listening/catching, those are good things :)</p>
</blockquote>
<p>Right.</p>
<blockquote>
<p>But are there other reasons either RL-related or not that you
chose to forgo that mechanism?</p>
</blockquote>
<p>Nope. Robotlegs is not imposing any restrictions whatsoever on
the way you’re listening for events in mediators.</p>
<p>I’ll try to make my point through examples.</p>
<p>Separation between framework and Views:</p>
<p>Views should be unaware of the framework, and the framework
should have as little knowledge about Views as even possible.<br>
The Views should be functional without a framework, or with any
other framework, not only the current one.<br>
Views should be re-usable.<br>
Framework classes should be re-usable in case the Views change
(other platform, touch and gesture user interactions….)</p>
<p>Of course, Mediators, being the link between Views and
Framework, have to know ‘something’ about their Views.
The Mediators have access to their Views through their API, and
they have to know how to translate Views events into framework
events.</p>
<p>In Mediator’s onRegister():</p>
<p>[1]
view.childView.someComponent.addEventListener(MouseEvent.CLICK,
onSomeSubComponentClick, MouseEvent);</p>
<p>[2] eventMap.mapListener(view.childView.someSubComponent,
MouseEvent.CLICK, onSomeSubComponentClick, MouseEvent);</p>
<p>[3] eventMap.mapListener(view, MouseEvent.CLICK,
onSomethingClicked, MouseEvent);</p>
<p>[4] eventMap.mapListener(view.someButton, MouseEvent.CLICK,
onSomeButtonClicked, MouseEvent);</p>
<p>[5] eventMap.mapListener(view.someButton, MouseEvent.MOUSE_OVER,
onSomeButtonOver, MouseEvent);</p>
<p>[6] <strong>eventMap.mapListener(view,
SomeEvent.SOMETHING_HAPPENED, onSomethingHappened,
SomeEvent);</strong></p>
<p>[1] and [2] The problem here is that the Mediator ‘knows
too much’ about View’s subcomponents and is digging too
deep into the display list’s hierarchy . Also, as mentioned
in a previous post, the event listeners would keep a reference to
the view, which in turn could keep the mediator from being removed.
In case 1, you’d have to remove the listeners manually, if
need be. The advantage of using the EventMap is that event
listeners are removed automatically, when the Mediator is
removed.</p>
<p>[3] Here, the mediator knows only about the top level view, but
the intention is not clear, and there are disadvantages like in [4]
and [5]</p>
<p>[4] and [5] If you changed your mind and wanted the event to be
dispatched on MouseEvent. DOUBLE_CLICK instead of MouseEvent.CLICK,
you’d have to change the code in your mediator accordingly.
Or, if the mediator should translate click, double_click, or
middle_click into the same framework event, you’d have to add
events listeners for all the occurrences.</p>
<p>Also, the Mediator still knows too much about the View.<br>
Plus, you cannot send data with plain events, unless you subclass
them and add properties.</p>
<p>[6] This is the better way, for a couple of reasons:</p>
<p>-stronger type-safety</p>
<p>-explicit intention/purpose (as you’ve noticed), clarity,
easier to follow the flow. A custom event, say,
FormEditEvent.FORM_EDITED, could be sent from different views to
their mediators, and you’d know exactly what that means just
by looking at the view’s code. This intention would be hidden
in [1] to [5]</p>
<p>-the Mediator is “ignorant” of which component or
user interaction issued the event, the View is encapsulated and
reusable. Different child views’ events can be translated
into the same custom event within ParentView.</p>
<p>-if you change View’s behavior, mouse over instead of
click, touch and gestures instead of mouse events, replace a List
with a DataGrid or vice versa, add or remove child views,
Mediator’s code stays the same. You could use the same
Mediator in a desktop, browser, or mobile app.</p>
<p>-easier to redispatch the same event: eventMap.mapListener(view,
SomeEvent.SOMETHING_HAPPENED, <strong>dispatch</strong>,
SomeEvent);</p>
<p>-Using a custom event makes it easier to transport data from
view to the application(and of course, the other way around too,
from application to mediator). The payload of the event can be
anything you want it to be, but you also can use VOs as
payloads.</p>
<p>So, bubbling events aren’t bad per se! I actually meant
scenarios like in [1] and [2], for the reasons mentioned above.<br>
You can let custom events bubble from deeply nested children, if
you want or need to.</p>
<p>Now, there is another aspect related to the topic, even if
it’s not your use case:<br>
A ParentView with many children: ChildViewOne,
ChildViewTwo…ChildViewTen.<br>
Decision to make:<br>
Should ParentViewMediator manage the events dispatched by its
ParentView and also by each of its children, or would it be better
to mediate each (major) ChildView?<br>
Answer: it depends on the use case and personal preferences. But,
if you notice that there are lots and lots of subcomponents letting
their events bubble up to ParentViewMediator that may be a sign
that you need a more granular design for your views. Just saying
:)<br>
[major child view = major functional area, not every and each
button, list, text field etc]</p>
<p>Ahh, my post ended up quite long, again ;)<br>
Ondina</p></div>Ondina D.F.tag:robotlegs.tenderapp.com,2009-10-18:Comment/188214432012-09-20T17:15:51Z2012-09-20T17:15:53ZEvents being caught intermittently <div><p>Well said!</p></div>John R. Nyquisttag:robotlegs.tenderapp.com,2009-10-18:Comment/188214432012-09-21T13:24:17Z2012-09-21T13:24:17ZEvents being caught intermittently <div><p>Thanks, John.<br>
I’m assuming this is resolved, thus I’m going to close
this discussion. Please feel free to re-open it, if you still have
any outstanding questions related to the topic.<br>
Cheers,<br>
Ondina</p></div>Ondina D.F.