Robotlegs Mediator Registration

by David Salahi on June 10, 2010

UPDATE June 10, 2010
NOTE: After I posted this shaun commented; (see comments on the single post page) pointing out my error. In Joel Hooks’ example the mediatorMap.mapView function calls are done inside the HelloWorldContext startup function. However, I had erroneously put the code into the context constructor. As shaun points out, this is too late in the creation process. Once I made that change everything worked fine.

However, I’ll leave this post up in case anyone else falls into this same trap. Maybe this will be of help in figuring this out.

I created a project with the code from Joel Hooks’ Robotlegs tutorial on InsideRIA and everything worked as expected. However, when I created another test project with some added features, I encountered some unexpected behavior in registering mediators. I eventually discovered that there is a difference in Robotlegs mediator registration depending on when in the main application life cycle the Context is created.

In my test project I had three MXML view files with three corresponding Mediators. In the Context constructor I called mediatorMap.mapView for each pair of views & mediators. But I called the Context constructor in three different ways and got three different results. What I experienced was that in one case only one Mediator onRegister function got called, in another case two of the three got called, and finally, in the third way all three got called. (All three getting called is the desired behavior, of course.)

Two Ways of Creating a Robotlegs Context

With most things MXML there are two ways of doing things: an MXML way and a corresponding ActionScript method. Creating a Robotlegs Context object  was no exception. The method shown in Joel Hooks’ example (as well as in many, if not all, of the Robotlegs demo apps) is to do it in MXML:

 <fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
<local:HelloWorldContext contextView="{this}"/>
</fx:Declarations>

Here, he creates a HelloWorldContext, which extends Context. A Context needs a reference to its DisplayObjectContainer so he uses the contextView property to set it to the containing MXML file. That works fine in his example but it didn’t work fine for me when I tried to extend the example in my own test. And it didn’t work fine when I tried extending his example to include a third mediator (for the main application). But before I explain that problem I’d like to take a little detour to show another problem that I encountered on the way to discovering the problem with creating the context in MXML.

When given a choice between doing something in MXML and ActionScript I generally prefer to do it in ActionScript. I’m not sure why but that feels more natural to me. Maybe that’s because I’m an old C/C++ coder going back to the days of MS-DOS. We didn’t have no stinking design view. And we liked it that way :) . I also prefer ActionScript because sometimes the MXML approach won’t work; e.g., when you need to create objects dynamically at run-time.

So, when it came time for me to create my test app, instead of creating my context in MXML, as above, I did it in code:

private var _context:GalleryContext;  // GalleryContext was my equivalent of Joel's  HelloWorldContext

private function init():void
{
_context = new GalleryContext(this);
}

Inside my GalleryContext constructor I was calling mediatorMap.mapView to associate each view with its corresponding mediator. The problem was that although I registered all three of my mediators identically only one of them was called, the one associated with the main application view. After carefully comparing my code with Joel’s the only significant difference I could find was the method of creating the context. So, I tried changing to the MXML method. To my surprise what happened is that the onRegister function for my other two mediators (for components)  were called—but not the one for my main application.

A Third Way of Creating a Robotlegs Context

I was beginning to suspect that the problem was related to the timing of various function calls during the app creation life cycle. When using the ActionScript method I had been using the applicationComplete event to call my init function in which I created my context object. So, I tried changing the event to creationComplete instead and, voila, my problem was solved. All three mediators were now called.

I’m new to Robotlegs and it occurs to me that maybe I’m using it in a way that it was not intended to be used. If so, I’d appreciate some enlightenment by someone in the know. For now, though, I’ve concluded that it’s safest to create the context in ActionScript and to use the creationComplete event handler to do it.

A modified copy of Joel Hooks’ example app is below. This version has an additional Mediator class, MainAppMediator. It also illustrates all three ways of creating the context and the three different results that are obtained. Two of the three ways are commented out. To see the different behaviors comment out the code as described by the comments in the main application file JoelHooksInsideRIA.mxml. To see the effect you have to then run it in the debugger (or use some other method of seeing the trace output). Right-click (in the Say Hello button area, not in the textarea below) to view source and download.

{ 2 comments… read them below or add one }

shaun June 10, 2010 at 1:44 pm

Hi David,

There are two reason why you were experiencing difficulties:

1. If you create the context after the view components are already on stage, then it is too late for Robotlegs to observe them landing on stage, and hence too late for it to perform automatic mediator creation. Constructing the context at applicationComplete is too late – the view components will already be on stage.

2. You are performing the mapping directly in your context’s constructor, which is incorrect. Instead, you should override the startup() hook and declare your mappings there (as shown in Joel’s article). The framework is not fully initialized inside the context’s constructor, so the mappings won’t function correctly.

Try moving your mappings into the startup hook and creating the context on creationComplete (or via MXML).

Hope that helps!

David Salahi June 10, 2010 at 3:18 pm

shaun,
Thanks a ton for your comments! Your sharp eye spotted my error. When I copied/pasted the code from Joel’s example I failed to notice that the mediatorMap.mapView function calls were inside the startup function but I had erroneously placed them inside the constructor. After I made the change all onRegister functions were then called both for the ActionScript and MXML methods of creating the context. And, as you say, when using the ActionScript method you have to use the creationComplete event construct the context.

David Salahi

Leave a Comment

 

{ 1 trackback }

Previous post:

Next post: