aodz

When you encounter issue wit your flex app, one useful tool for troubleshooting is to turn on debug in flex to get some output that will provide some clue of the cause of he problem. Here is how to turn it on from server-side as well as from client-side:

1. From server side:
In the services-config.xml, set the logging level to debug, and set filters to include the service you need:

<target class=”flex.messaging.log.ConsoleTarget” level=”debug”>
<properties>
<prefix>[Flex hotfix2] </prefix>
<includeDate>true</includeDate>
<includeTime>true</includeTime>
<includeLevel>true</includeLevel>
<includeCategory>true</includeCategory>
</properties>
<filters>
<pattern>Endpoint.*</pattern>
<pattern>Service.*</pattern>
<pattern>Protocol.*</pattern>
<pattern>Message.*</pattern>
<pattern>DataService.*</pattern>
<pattern>Configuration</pattern>
</filters>
</target>

See available pattern in doc:
http://livedocs.adobe.com/livecycle/8.2/programLC/programmer/lcds/help.html?content=services_logging_3.html

2. To turn on trace in JGroup:
in jgroups-tcp.xml, add <TRACE/> tag just before the </config> line :

<config>
….
<TRACE/>
</config>

3. To turn on from client-side:
Make sure flashlog.txt is enabled, i.e, have the following setting in mm.cfg
TraceOutputFileEnable=1
ErrorReportingEnable=1
See more details in the doc here
There is a good blog regarding mm.cfg here as well.
Then in your flex app, add the following tag:
<mx:TraceTarget/>

4. To turn on the flash player policy logging

see http://www.adobe.com/devnet/flashplayer/articles/fplayer9_security_05.html

Original post

Advertisements
Tags: , ,

Here is an example of Data grid filtered using a H slider  with 2 thumbs to select the range of date for which to  filter the data grid. The combo box is used to select the specific column on which the filter has to be applied to. The check box is used to either enable or disable the filter functionality.

Screenshot:

testfilterdg

For source please read the complete article Read the rest of this entry »

FrameworkQuest Part 6 by Tony Hillerson
Find the original post here

FrameworkQuest 2008: Introduction
FrameworkQuest 2008 Part 2: Get Control with Cairngorm
FrameworkQuest 2008 Part 3: Agnostic Views with PureMVC
FrameworkQuest 2008 Part 4: IoC With Swiz
FrameworkQuest 2008 Part 5: Mate, the Pure MXML Framework
FrameworkQuest 2008 Part 6: The Exciting Conclusion

Well kids, it’s been a wild ride. We’ve looked at five
implementations of a simple Twitter client built with no framework, Cairngorm,
PureMVC, Swiz, and Mate. We’ve talked about important things like pronouncing
the framework’s names, architectural patterns, Inversion of Control, and
programmer joy.

In this last part, I’m going to turn off any semblance of
objectivity and let you know what I think about these frameworks. If you’re not
interested in what I think, I don’t blame you, but I also don’t want anyone to
take my word for it and blindly choose which one I like. Take a look at the
examples and see which one you’d rather work with. Come up with a simple
application and build it four different way. In other words, try before you
buy.

Ok, here we go. First, in prose, and then with some numbers.

Cairngorm

As I mentioned early on, I’ve been using Cairngorm for a while
now. Does that make me want to stick with it or try something new? Well, I’ve
liked using Cairngorm. I also like to use Christophe
Herreman
‘s  Prana
to help out a bit with sequences of commands and IoC. In fact, I wanted to have
an article on Prana

in this series, but I just ran out of time. You can settle for this blog post about delegate factories, which shows
how we might have made our dummy data solution a little more palatable.

The thing I like most about Cairngorm is the command pattern. I
really like having commands that are named with a description of what they do,
and I really like that everything to do with getting that specific task done is
inside the command.

Cairngorm, though, being around the longest and the loneliest,
has attracted criticism. It’s surprising to me, because I think it’s not a bad
framework, and not even that heavyweight. Even so, I came into this article to
try out these other frameworks and see if one struck me as something I’d rather
work with from day to day. Let’s have a look at some criticisms.

Some people don’t like Cairngorm’s verbosity when it comes to
defining a new command. I don’t think there’s anything wrong there that can’t
be solved with some code generation, but I agree that it’s pretty
verbose.

Other arguments against Cairngorm are usually leveled against its
use of a Singleton model. A Singleton makes unit testing hard, and sometimes
people say it’s just a glorified "global variable". Let’s take these
one at a time.

Singletons are not "global variables". People make fun
of using global variables because it’s a rookie way of getting around building
a good architecture. It was the way we built Flash apps before we knew how to
program. That’s true – global variables are unsafe because there’s no guarantee
who’s accessing and changing them. In short, there’s no encapsulation. But with
a Singleton, there is encapsulation, because what you’re dealing with is still
an object. There’s nothing stopping you from using read-only getters instead of
public properties.

Singletons do, however, make it harder to unit test, because a
simple test that, say, runs a command sequence and tests that a property on the
model changed as expected, changes that model instance of which there is only
one. The more tests, the more the model gets into a strange initial state. I
think that’s not that big of a deal if you just take the time to reset the
model to a known state before each test. If you have to have a “logout” in your
app anyway, you’ll need to do something like that anyway (unless you cop out
and just refresh the page with javascript). I agree, though, that it’s extra
code to maintain.

One last problem people have is that Cairngorm has you putting
Cairngorm events on the view. That means you have to make a Cairngorm event,
first, and second it means that you have framework code on the view that makes
it hard to refactor away from Cairngorm.

Now, look. How many times in an app do you just scrap it and
switch frameworks? I never have. I agree that componentizing is great when you
really have a view you can turn into a blackbox component, but if you have a
view specific to a certain app I really don’t see that it’s anything but bikeshedding
to try to make the view code re-usable. There’s a point of diminishing returns,
and at that point or even a little before, you should just move on and get the
app done. That’s why I don’t care that much about Flex framework code in a Flex
application. I’m certainly open to the idea of using regular Flash events,
though, so that brings us to PureMVC.

PureMVC

One way I describe the difference between Cairngorm and PureMVC
to people is that Cairngorm doesn’t have much to say about your view code, and
PureMVC doesn’t have much to say about your service access code. That’s why you
see the BusinessDelegate pattern in PureMVC and Cairngorm – because it works
well.

What PureMVC tries to fix, though, is having the view cluttered
with PureMVC code. It fixes that well – the only place you have to put PureMVC
code is on the root application. As far as that goes, I like using Flash events
instead of Cairngorm events. What’s nice there is that if I’m using a blackbox
component that emits Flash events, I can still easily respond in a Mediator
whereas in Cairngorm I’d have to catch and re-dispatch an event as a Cairngorm
event if I wanted to take action.

One other important PureMVC goal is to be an Actionscript
framework, not a Flex framework. That means I can’t (or shouldn’t) use Flex
binding to wire up a view to a Proxy, I need to have the Mediator do it. Is
that a win? I think binding is great, and I also think it needs special
understanding to use it correctly. In a medium to large sized application, by
using binding right out of the box, you can cause a really huge event storm
whenever any bound property changes and bring performance to a halt.

I think binding is good when used responsibly, so when PureMVC
says to skip it, I’m interested, but I want to know what it costs to use. So
what I don’t like about PureMVC is how much boilerplate code there is. I like
the idea of a mediator for views, but there is so much set up to do. The
constants, the viewComponent
wrapper, listNotificationInterests,

handleNotification,
there’s a lot of stuff it takes to set up a Mediator. I like PureMVC in
general, but I’ve never gotten up the energy to use it on a project because of
inertia. It feels like it’s a big investment to do things the PureMVC way.

Contrast that with the lightest weight framework, Swiz.

Swiz

I have to be honest, when I wrote this article because of the
buzz and Laura’s presentation at 360 Flex San Jose, I
was really prepared to like Mate hands down. (BTW, here’s Chris’s presentation). When I
started using Swiz, though, I immediately felt the joy. You know what I’m
talking about – that sense that you’re in the groove and building something and
there’s not much work between having an idea and implementing it.

I’m going to make a distinction that I haven’t heard before, or
at least don’t remember hearing. I think there are proscriptive and prescriptive tendencies to software
frameworks. On the one hand, proscription means saying what you can’t do, and
on the other, prescription means saying what you could do. Whereas PureMVC says
a lot of things you shouldn’t do and some things that you can do, Swiz almost
completely sticks to saying what you can do.

Swiz leaves a lot up to you. All it does is provide some easy
ways to do things like inject a controller or a model into the view and to
easily wire up events with the Mediate metadata tag. From there on out, it’s up
to you. Swiz is the laissez faire framework, and I really like that.

The only thing is that all the service interaction stuff, the
dynamic delegates and command all expect you to be using RemoteObjects and
delegate methods that return AsyncTokens. I’m sure this could be fixed, but
unless I’m missing something until it is fixed Swiz is less useful to anyone
not using AMF services. Since I’m used to using RubyAMF,
that’s great for me, but I can’t always count on it or BlazeDS or ColdFusion
being on the server side. You can work around it, but it’d be nice to have
those tools available for other types of services.

One thing I’d also like to see is an easy way to use the command
pattern where logic is actually written in the commands. I really like that
pattern because I think it’s cleaner to have logic in commands instead of in
controller files that have to do with more than one type of data or view.
Controllers tend to get a little big, especially with callbacks.

That said, I really like Swiz and I think Autowire and Mediate
are enough incentive to use it over Cairngorm or PureMVC. Swiz is the style of
programming that those three frameworks represent done right. Mate, however, is
a different, hmm… what should I say… cup of tea?

Mate

Mate is picking up a lot of steam lately (these puns are going to
keep on coming, people, you may as well just laugh now). Everyone I talk to lately
loves it. I think it’s a shame that some of those people aren’t really getting
a chance to try Swiz too, but when you feel what it’s like developing with
Mate, you’ll see that it’s not that big of a shame.

The way I make a distinction between Swiz and Mate is that Swiz
is the Cairngorm style done right, while Mate is a completely different style.
The big difference, I think, is the declarative versus programmatic style of
Mate. Since a lot of what we do in Flex is in MXML, using MXML to set up framework
interaction makes a lot of sense, and also just seems to really fit alongside
the view code.

PureMVC and Mate both want you to use regular old Flash events
instead of framework prescribed events. Swiz wants that too, but sometimes you
need to dispatch through its dispatch system. What makes Mate so elegant,
though, was the insight of just using the event-bubbling to catch them with the
EventMap without defining a bunch of wiring code. Of course, that breaks down
when you want to use a service delegate and have to pass in the dispatcher, but
it doesn’t break down as hard as Swiz breaks down when you don’t use
RemoteObjects.

Mate is also really flexible. There are probably more tools there
than you need, and not only that, it has a plugin
structure
. I don’t understand it yet, but that’s kind of nice. I
also like that Mate has a way of using Commands, although I’m not sure it would
be worth it to just turn your EventMap into a Cairngorm FrontController.

I like Mate a lot and I can’t find anything to pick on. Really.
The only thing is I don’t think I fully understand how it scales, and the way
it does view and object cacheing is a little bit of magic. Magic isn’t bad, but
again, I just don’t know what pitfalls await me while using it. I hope to find
out, though, and I’m really excited to use Mate.

Framework Smackdown

Now is the time when I give you my subjective rating system to
give a bit more quantification. Below is a table rating the frameworks on five
variables from 1-5, 5 being high:

1.    Conciseness – How little it takes to get something done in the
framework.

2.    Familiarity – Once you get past the initial learning phase, how
easy is it to fall into the pattern of using the framework. How easy is it to
think in the framework?

3.    Flexibility – How easy it is to work with exceptions to normal
development patterns.

4.    Power – The tools to get the job done

5.    Programmer
Joy
– Is it fun to use the framework? Is
it rewarding, or does it punish you when you have to use it?

Conciseness

Familiarity

Flexibility

Power

Joy

Total

Cairngorm

2

4

4

3

3

16

PureMVC

1

2

5

3

1

12

Swiz

5

5

2

2

4

18

Mate

4

4

4

5

5

22

Well, there you have it, folks. I’m riding into this one with
flame-proof-pants on, but I hope I’ve done a little good by giving the
reasoning behind my thinking. I welcome any critique of my reasoning, and if
there’s a better way to do something in my example code please put comments on
the code in Github and leave a note here as well. I hope
the example applications help, and I hope that you’ve all learned a little bit
about yourselves on this journey. Viva Flex.

Read more from
Tony Hillerson
.

Tags:

FrameworkQuest Part 5 by Tony Hillerson
Find the original post here

FrameworkQuest 2008: Introduction
FrameworkQuest 2008 Part 2: Get Control with Cairngorm
FrameworkQuest 2008 Part 3: Agnostic Views with PureMVC
FrameworkQuest 2008 Part 4: IoC With Swiz
FrameworkQuest 2008 Part 5: Mate, the Pure MXML Framework
FrameworkQuest 2008 Part 6: The Exciting Conclusion

Let’s get this out of the way first thing. It’s Mah-tay, not
M-eight. Like the drink, the creators of Mate, Nahuel Faronda and
Laura Arguello
, come from Argentina. If you’ve never tried Mate (the
drink), you should – it’s tasty. If you’ve never tried Mate

(the framework), well, that’s tasty, too, and you’re about to dig into a big
bowl full. Sorry about that mixed metaphor there.

Mate is design to take advantage of MXML and regular old Flash
events dispatched the regular way, not through the framework like Cairngorm or
Swiz (although Swiz is open to regular event dispatching if you set it up
yourself). In that way it’s like PureMVC. But Mate uses the fact that part of
the framework is defined right at Application level to make the event-driven
part of the framework very unobtrusive and easy.

Since it’s very unobtrusively event based (you’ll see what I mean
in a bit) it allows you to make a very componentized application easily, and
although of course you can use the classes from the framework in ActionScript
form, you’ll be surprised at how much you can do right in MXML.

Let’s look at one of those green box things again. The Delegate is yellow to
show that it’s optional.

So when a user interacts with the view, and event is fired. The EventMap, declared on
the root application receives all events dispatched anywhere in the view as
long as the bubbles
property of the event is set to true. So the basic way of acting on some user
input is to dispatch a custom event with the bubbles property set to true. This is
how Mate is so unobtrusive. You don’t have to define event listeners all over
the place, just define some code in the EventMap to catch certain types of
events. The EventMap
takes care of calling the service in simple situations, but it could delegate
the service call to a delegate as well.

The EventMap
could also fire off a command, Cairngorm style, if you
like that way of doing things better. Mate is a very flexible framework. In
fact, there are a lot more parts to Mate than are listed here and any of them
could be used to do things a different way or to deal with exceptions. Mate’s
documentation is particularly good and easy to use compared to the other
frameworks, so have a look at it if you want.

To get data into the view, Mate either defines an IoC style Injector or simply
dispatches an event with an EventAnnouncer
and the view can use Mate’s Listener
tag to be notified of these events. We’ll see both ways of doing things.
Storing data in the model is delegated to objects that most of the examples
call Managers.
Some examples use a Manager
to actually do service interaction. Again that’s up to you and how pure you
want the model to be.

Ok, let’s start looking into how I did this application the Mate
way.

Twitter Through A Bomba

The first Mate specific code in our app is on the root
application.

twitteria_mate/src/twitteria_mate.mxml #21

<maps:MainEventMap />

The EventMap
is central to any Mate application, so it’s defined early. Note that although
we only have one, you can have as many as you want, so you can break things up
as clean as you want them.

Each application defines its own EventMap, and ours is imaginatively
called MainEventMap.
There’s not a lot more to see on the application, so let’s look at logging in.

Logging In

Once again, hitting enter in the password field kicks off the
login process. It calls the login
method on LoginView.

twitteria_mate/src/com/insideria/twitteria/view/LoginView.mxml
#10-13 (formatted)

public function login():void {
      var le:LoginEvent = new LoginEvent(
           usernameText.text, passwordText.text

      ); 
      dispatchEvent(le);
}

We dispatch a LoginEvent
and send along the username and password. Nothing framework specific. Let’s
look at the LoginEvent.

twitteria_mate/src/com/insideria/twitteria/events/LoginEvent.as
#7-16 (formatted)

public static const LOG_IN:String = "login";


public var username:String;
public var password:String;

public function LoginEvent(username:String, password:String) {
      super(LOG_IN, true, false);
      this.username = username;
      this.password = password;
}

First, we keep a constant on the event to make sure the type of
the event is clear. We also have a place for the username and password payload. The super call is
important. The arguments are ‘type’, ‘bubbles’, and ‘cancelable’. The type is
our constant, and bubbles is set to true. That’s important because when an
event bubbles it moves all the way to the top of the display object tree and
anything in the tree can listen for it. The EventMap ultimately listens for this
event.

twitteria_mate/src/com/insideria/twitteria/maps/MainEventMap.mxml
#13-16 (formatted)

<EventHandlers type="{LoginEvent.LOG_IN}" debug="true">

     <ObjectBuilder
          generator="{TwitterDelegate}"
          constructorArguments="{[
               event.username, event.password, scope.dispatcher
          ]}" />
     <MethodInvoker
          generator="{TwitterDelegate}"
          method="loadTimeline" />
</EventHandlers>

Wow. There’s a lot going on here, so let’s break it down. The EventHandlers tag
defines the actions to take for a certain type of event, designated in the type property. This
corresponds to the constant in our LoginEvent, so this is the event handler for when that
event bubbles up.

When that event gets caught, the first tag takes over. The ObjectBuilder
tag creates an object of a certain type, which is set in the generator property. That can be either
a fully qualified path as a string, or a class in a binding, like we have. The
default behavior is to create an object of that type and keep a reference to it
indexed by type. That means that any another object of that type is requested,
the cached object will be returned. This is how Mate deals with the problem
that Cairngorm deals with using singletons, that of keeping an instance of an
object easy to get to.

The constructorArguments
are, of course, how you pass in arguments to the class’ constructor. Here we
pass in, from the incoming event, the username, password, and from the scope property of the

EventMap, a dispatcher. Hopefully
the event properties are clear enough to you. The dispatcher thing needs to be
cleared up a bit though, I bet. What we’re going to do, since we don’t have a
standard service to call, like a RemoteObject, WebService, or HTTPService, which all have invokers in Mate, is to have a delegate that
dispatches events when things happen. To make that work with any Mate Listeners, which
we’ll see in a bit, we need to dispatch the events through Mate. This dispatcher passed
into the TwitterDelegate’s

constructor lets us do that.

Next, we use a MethodInvoker
tag to invoke a method on the TwitterDelegate,
namely loadTimeline.
The MethodInvoker
uses the same generator style. Since the defaults are in place on the ObjectBuilder, the
object that was built there will be reused here. In fact, We didn’t even really
need to use the ObjectBuilder,
because the generator in MethodInvoker

would have cached the class too. That’s the default behavior of most of the
tags used in the EventMap.
Why did I use the ObjectBuilder
then? Just to show it could be done and to make it explicit. Look, I’m trying
to teach here.

That was a lot of explanation for two or three tags, so let’s say
it in plain English. When the EventMap
gets the LoginEvent,
it builds a TwitterDelegate

and caches the instance for whenever another TwitterDelegate is requested. Then we
invoke loadTimeline
on a TwitterDelegate,
which uses the cached instance. Let’s see what happens in the delegate.

Loading The Timeline

Just like before, we decide on using the dummyData or not, and possibly call
the Twitter service.

twitteria_mate/src/com/insideria/twitteria/business/TwitterDelegate.as
#33-42 (formatted)

public function loadTimeline():void {
      if (useDummyData) {
            var te:TwitterEvent = new TwitterEvent(
                 TwitterEvent.ON_FRIENDS_TIMELINE_RESULT
            );
            te.data = getDummyData();
            friendsTimelineLoaded(te);
       } else {
            twitterService.loadFriendsTimeline(username);
       }
}

And either way, the callback is executed.

twitteria_mate/src/com/insideria/twitteria/business/TwitterDelegate.as
#53-56 (formatted)

private function friendsTimelineLoaded(te:TwitterEvent):void {
      var e:TimelineReceivedEvent = 
           new TimelineReceivedEvent(te.data as Array);
      dispatcher.dispatchEvent(e);
}

This time it’s different, though, and we get together a TimelineReceivedEvent
with the array of tweets and dispatch it through the dispatcher we got from the
MainEventMap
when the delegate was constructed.

The MainEventMap

is listening for that kind of event:

twitteria_mate/src/com/insideria/twitteria/maps/MainEventMap.mxml
#18-21 (formatted)

<EventHandlers 
     type="{TimelineReceivedEvent.TIMELINE_RECEIVED}"
     debug="true">

     <MethodInvoker
          generator="{TwitterManager}"
          method="setCurrentTweets"
          arguments="{[event.tweets]}" />
     <EventAnnouncer
          generator="{ViewStateEvent}" 
          type="{ViewStateEvent.SHOW_MAIN_VIEW}"
          bubbles="true" />

</EventHandlers>

When it gets it, it invokes setCurrentTweets on a generated TwitterManager and
passes the tweets we set on the event. It then uses an EventAnnouncer
to fire a ViewStateEvent

of type ViewStateEvent.SHOW_MAIN_VIEW.
Let’s take those one at a time.

The TwitterManager
is our model-type object, following what I take to be a Mate naming convention.
It’s simple enough.

twitteria_mate/src/com/insideria/twitteria/business/TwitterManager.as
#5-12 (formatted)

public class TwitterManager {
      [Bindable]
      public var currentTweets:ArrayCollection;
     
      public function setCurrentTweets(tweets:Array):void {
            currentTweets = new ArrayCollection(tweets);
       }

It just has a Bindable collection of tweets and a way to set them. Now
that they’re set, how do they get to the view? A PropertyInjector, with the help of Flex
binding.

twitteria_mate/src/com/insideria/twitteria/maps/MainEventMap.mxml
#31-33 (formatted)

<Injectors target="{MainView}">
     <PropertyInjector
          source="{TwitterManager}"
          sourceKey="currentTweets"
          targetKey="currentTweets" />

</Injectors>

This is another very Mate way of doing things. This is saying
that Mate should bind the currentTweets
property of any cached TwitterManager
into the cached MainView
instance’s currentTweets.
Hold on, when did a MainView

get cached? Well, as a service to the user, Mate listens for the event from any
view (I believe the creationComplete
event) just like it does for any other user defined bubbling event, and then
caches a reference to that view. That way the EventMap has a way to communicate with
the view of any type. Sneaky, eh? I thought so. Now whenever the currentTweets on our
manager changes, that view will be updated. Now we have the data getting to the
right view, but how do we get the ViewStack on the application onto the right index?

That second tag, the EventAnnouncer fires off a ViewStateEvent.

twitteria_mate/src/com/insideria/twitteria/events/ViewStateEvent.as
#7-11 (formatted)

public static const SHOW_MAIN_VIEW:String = "showMainView";

public function ViewStateEvent(
                               type:String,
                               bubbles:Boolean=true,
                               cancelable:Boolean=false) {
      super(type, bubbles, cancelable);
}

Since we’re using the EventAnnouncer to fire this off, it needs the standard
event constructor. Also, we could have lots of view state constants to use for
different view state events since Flash events are unique by sort of a weird
mix of class and type property. So where does this event go? Well, if we look
back on the application, we’ll see.

 

twitteria_mate/src/twitteria_mate.mxml #23 (formatted)

<mate:Listener
     type="{ViewStateEvent.SHOW_MAIN_VIEW}"
     method="showMainView" />

Here’s a Listener

tag that listens for just that event type. When it gets it, it calls showMainView.

twitteria_mate/src/twitteria_mate.mxml #7-12

public const LOGIN_VIEW:int    = 0;

public const MAIN_VIEW:int     = 1;

private function showMainView(e:Event):void {
      mainViewStack.selectedIndex = MAIN_VIEW;
}

That method sets the view stack to where it should be. Now we
have the MainView
showing in the ViewStack
and right data in the list in MainView.
Let’s have a look at setting status now.

Setting Status

As you probably can guess, we set status by firing off an event.
Here’s where we do it:

twitteria_mate/src/com/insideria/twitteria/view/MainView.mxml
#12-16

private function setStatus():void {
      var e:SetStatusEvent = new SetStatusEvent(statusText.text);
      dispatchEvent(e);
      statusText.clear();
}

And here’s where it ends up:

twitteria_mate/src/com/insideria/twitteria/maps/MainEventMap.mxml
#23-25 (formatted)

<EventHandlers type="{SetStatusEvent.SET_STATUS}" debug="true">

     <MethodInvoker
          generator="{TwitterDelegate}"
          method="setStatus"
          arguments="{[event.statusText]}" />
</EventHandlers>

We call setStatus
on the cached TwitterDelegate,
passing in the statusText
from the incoming event.

twitteria_mate/src/com/insideria/twitteria/business/TwitterDelegate.as
#58-61

private function statusSet(te:TwitterEvent):void {
      var e:StatusSetEvent = new StatusSetEvent();
      dispatcher.dispatchEvent(e);
}

When the delegate is done, it dispatches a StatusSetEvent through
its dispatcher.

 

twitteria_mate/src/com/insideria/twitteria/maps/MainEventMap.mxml
#27-29 (formatted)

<EventHandlers type="{StatusSetEvent.STATUS_SET}" debug="true">

     <MethodInvoker
          generator="{TwitterDelegate}"
          method="loadTimeline" />
</EventHandlers>

Back in the EventMap,
it catches that event and reloads by calling back to the delegate, which kicks
off that whole chain again.

Next Up

Mate’s sort of a different beast from the other frameworks. The EventMap approach is
novel, as is the class caching. Once you see how it works, it’s a lot of fun to
use, though.

Now we’ve built our application using four different Flex
frameworks. Again, although it wasn’t an exhaustive look at each framework or
its capabilities, and since our use cases may have been a little out of the
ordinary especially around the delegate area, I hope that this has at least
shown you how it feels to use these frameworks in a day-to-day setting.

Next up, we’re going to get into the opinion section of the app,
where I tell you how I think each framework stacks up against the others, which
one I’d like to use from now on, and which one I think renders the most
Programmer Joy.

Read more from
Tony Hillerson
.

Tags:

FrameworkQuest Part 4 by Tony Hillerson
Find the original post here

FrameworkQuest 2008: Introduction
FrameworkQuest 2008 Part 2: Get Control with Cairngorm
FrameworkQuest 2008 Part 3: Agnostic Views with PureMVC
FrameworkQuest 2008 Part 4: IoC With Swiz
FrameworkQuest 2008 Part 5: Mate, the Pure MXML Framework
FrameworkQuest 2008 Part 6: The Exciting Conclusion

With a name like Swiz, it has to be good, right? Welcome back,
friends, to part four of our ongoing effort to understand these four Flex
frameworks. This time we’re going to look at Swiz, a relative newcomer, created
by Chris
Scott
. Chris had a simple idea to use a powerful but underused Flex
feature, Metadata, to implement a concept called Inversion of Control.

Sounds scary? Actually, the point of this effort is to make
things easier for you. A big part of the frameworks we’ve looked at so far is
not just some classes that you have to create, but some wiring you have to do.
You have to make some framework classes, describe them to the framework, and
make sure that the code describing them gets called. That overhead can feel
like a drag on productivity and maintainability. That’s one thing that
Inversion of Control is made to fix.

Here’s an example of what we’re talking about. Remember last week
when we set up Mediators
to work with the application view, LoginView, and MainView? We fired off a PureMVC command called ViewPrepCommand that
reached in and got the reference to each view, created an ApplicationMediator, LoginViewMediator, MainViewMediator, and passed the views
in to each. It doesn’t make any difference that we pushed that code into a
Command to keep the view clean, we still had to write the code to take those
steps. Same thing when we wrote the code to associate LoginEvent with LoginCommand in the TwitteRIAController in the Cairngorm
example. We had to go one place to write the code for the event, another place
to write the code for the command, and then another to say that we wanted the
one to associate with the other. Wouldn’t it be nice if we could, with a
minimum amount of code, ask the framework to do that for us?

Consider Flex Binding. Lovely, isn’t it? You mark a property as [Bindable], and then
elsewhere you can use the curly brace notation to tell Flex that you want to
wire that value up to another property and update that destination property
whenever the other changes. This is a lot like Inversion of Control.

The control that we’re talking about here is actually a
responsibility – responsibility to get the resources that a particular
component needs in place. In the current paradigm we’ve been working with, the
component, or a delegate that we create, is responsible for getting the
component’s stuff together. IoC means to invert that responsibility up out of
the component and into the framework. Instead of going to find and wire up what
it wants, a component instead just lets the framework knows what it wants, and
the framework does the rest. This requires the component to have knowledge of
the framework, but not to have to know the details of where to get things.

We’ll get to see IoC in action with Swiz in a bit, but first
let’s talk for a second, as we have with the other frameworks, about how the
Swiz flow of events works.

Pretty simple, eh? The user interacts with the view and the view
notifies the Controller.
How that happens is up to you. You could use events and set the Controller up as an
event listener, or you could call the Controller directly. If there’s service work to be done,
the Controller

will call a Delegate
and the Delegate
can call the service. Swiz makes it dead simple to wire up the Controller/Delegate
communication – IF – the service is an AMF service that you can contact with a RemoteObject. If the
service is not a RemoteObject
you have to fend for yourself as I found out. More on that in a bit.

When the service call is over and the Controller gets notified, the
controller can put some data on the model and act on the view as necessary. The
Controller is
free to wire up data from the Model
to the view PureMVC style, or you can use Binding and let Flex do the work.

Again, pretty simple. But it’s no more than you need to get the job done. The app is separated
into the three concerns, services are encapsulated, and the best part, which
we’ll see next, is that Swiz takes care of wiring all this stuff together.

You Turn Me Right ‘Round, Baby

That’s an IoC joke, right there. Moving along let’s look in the
root application to see some characteristic Swiz code.

twitteria_swiz/src/twitteria_swiz.mxml #20-22

[Bindable]

[Autowire(bean="model")]

public var model:TwitteRIAModel;

This is the reference to the model that the application uses to
drive the ViewStack,
as it does in the Cairngorm application. You’ve seen a [Bindable] tag before, but what’s that other tag underneath there? Autowire is a Swiz
metadata tag. Flex has had metadata around for a while, but recently
allowed a compiler option to keep custom metadata. The Swiz swc library adds two
tags to the list of metadata that the Flex compiler will keep around, Autowire, and Mediate. We’ll look
at Mediate in a
bit, but Autowire

is the first example of Swiz’s IoC at work. It’s essentially saying “When this
view is constructed, go find a bean
named ‘model’ and set this property,
model, to point to it”. If you’ve come
from Java-land to Flex, you know what we mean by bean, but others may not. Lots of talk about beans in
Java-land, for those of you who don’t know, but all they mean is some sort of
component. Don’t worry about it, and feel free to make as many jokes as you want.
As far as I’m concerned, they’re all deserved. Beans! Come on. Don’t even get
me started on POJOs.

In case you didn’t notice, this Autowire thing is sweet. We don’t have
to worry about where this model comes from. We don’t have to think about if it’s
a Singleton or not. All we know is that we want a model, and the framework will
make sure we have one when we need it. One note of caution: the property has to
be marked public
or Swiz won’t be able to assign to it.

So where do these magical beans come from? Well, there is one bit
of administrativa we need to take care of to get those beans jumping for us.

twitteria_swiz/src/twitteria_swiz.mxml #8, 24-26

preinitialize="loadBeans()"
...

private function loadBeans():void {
      Swiz.loadBeans([Beans]);
}

On preinitialize,
which is very early in the Flex bootstrapping process, we call loadBeans, which
delegates up to Swiz and mentions where to find them. It’s important that this
happen at preinitialize
so that Swiz is all ready to go when views that use Swiz metadata are created,
including the application itself. Now let’s look at the bean definition file.

twitteria_swiz/src/com/insideria/twitteria/Beans.mxml

<BeanLoader
     xmlns="org.swizframework.util.*" 
     xmlns:api="twitter.api.*"
     xmlns:delegates="com.insideria.twitteria.delegates.*"
     xmlns:model="com.insideria.twitteria.model.*"
     xmlns:controllers="com.insideria.twitteria.controllers.*">

     <controllers:ApplicationController id="applicationController" />
     <controllers:LoginViewController id="loginViewController" />
     <controllers:MainViewController id="mainViewController" />
     <model:TwitteRIAModel id="model" />

</BeanLoader>

This BeanLoader
is just an MXML file with a tag for any class that you want to Autowire anywhere in
the application. Inside we have all the controllers and the model. Notice that
the call to loadBeans
passes an array, so it’s possible to split up the bean definitions over
multiple files for good housekeeping.

I decided to use the Flex binding way of wiring up the view to
the model, so that instance that points at model is fair game, just as if we’d
looked it up as a Singleton, a la Cairngorm, or gotten ahold of it some other
way.

twitteria_swiz/src/twitteria_swiz.mxml #37 (formatted)

<mx:ViewStack selectedIndex="{model.mainViewIndex}">

Logging In

Just as before, when pressing enter in the password field on
LoginView, the login process is kicked off. Here’s what it looks like with
Swiz.

twitteria_swiz/src/com/insideria/twitteria/view/LoginView.mxml
#9-14 (formatted)

public function login():void {
      var e:DynamicEvent = new 
           DynamicEvent(LoginViewController.LOG_IN);
      e.username = usernameText.text;
      e.password = passwordText.text;
      Swiz.dispatchEvent(e);
}

First thing we do is to created a DynamicEvent, which is a little used
(as far as I know) Flex event that is a dynamic class. That means we can assign
to whatever properties we want on it, just like ActionScript’s Object. Swiz doesn’t
mandate the use of DynamicEvents,
but it slyly suggests that we can use this class instead of the more
time-consuming method of creating a new Event for each type of payload. Just
remember if you use dynamic objects that the compiler won’t catcher errors for
you if you misspell things, but that’s what unit tests
are for, right?

Our payload this time is the username and password. Instead of
dispatching an event the regular way, we dispatch events through Swiz if we
want framework classes to get them. Notice that there’s no controller instance
specified on the LoginView,
nor does LoginViewController
know anything about the view (although both could be true if the application
needed it), but LoginViewController
is still out there waiting for this LOG_IN event, because it was instantiated in the BeanLoader. How does
the controller sign up to get events? Like this:

twitteria_swiz/src/com/insideria/twitteria/controllers/LoginViewController.as
#18-25

[Mediate(event="login", properties="username,password")]
public function login(username:String, password:String):void {
      model.username = username;
      model.password = password;
      var e:Event = new Event(LOGIN_COMPLETE);
      Swiz.dispatchEvent(e);
}

Here’s the other metadata tag we mentioned, Mediate. The Mediate tag goes on controller methods
that you want called when a certain type of event is dispatched through Swiz.
The event argument to the tag needs to match the string type of the event, but
sadly it’s not possible to make this point to the same constant that defines
that string at this point. Just keep an eye out that they’re the same.

The tag’s properties argument tells Swiz which properties of the
incoming event it should grab and pass into the tagged method. The gain is that
you don’t have to add an event listener somewhere else, you have the code right
here annotating the method. Also, you don’t have to do the boilerplate event
wrangling to get data you need out. You say what data you’re expecting and from
what type of event, and the framework will get it out for you. That means you
can just write regular functions, which has the added benefit of letting you
call those functions from other code that doesn’t use events. I didn’t test it,
so don’t quote me on it, but it’s also theoretically possible to have more than
one Mediate tag
per method, I suppose.

Inside the login
method we set the username and password on the model, which is, of course, Autowired up on the
controller as well.

twitteria_swiz/src/com/insideria/twitteria/controllers/LoginViewController.as
#15-16

[Autowire(bean="model")]

public var model:TwitteRIAModel;

After setting those properties on the model, it then dispatches
an event saying that log in is complete. Notice that instead of a DynamicEvent, we’re
using just a regular Flash Event

here. Either one will work, and Event
is fine when we don’t have to carry a payload.

The next step after logging in is loading the timeline, and we do
that on the MainViewController.

Loading The Timeline

When the MainViewController
is instantiated from the BeanLoader,
it registers to receive the log in event right away.

twitteria_swiz/src/com/insideria/twitteria/controllers/MainViewController.as
#22-24


public function MainViewController() {
      Swiz.addEventListener(
           LoginViewController.LOGIN_COMPLETE,
           loginComplete
      );
}

This is another way to listen for events sent through Swiz
besides Mediate.
Once the event is received, loginComplete
is called.

twitteria_swiz/src/com/insideria/twitteria/controllers/MainViewController.as
#53-55

private function loginComplete(e:Event):void {
      loadTweets();
}

twitteria_swiz/src/com/insideria/twitteria/controllers/MainViewController.as
#31-34

public function loadTweets():void {
      var delegate:TwitterDelegate = new TwitterDelegate(this);
      delegate.loadTimeline(username);
}

Now comes the point where we call the delegate to get the latest
timeline. Now, as I mentioned before this part is really easy if you’re using a
service that is wrapped by a RemoteObject.
Then all you’d do is call createCommand,
passing the delegate method to call, its arguments, and a result and fault
callback. As long as the delegate method returned an AsyncToken object, Swiz would then
take care of all the callbacks. That’s a nice set up, but unfortunately it
doesn’t work for us, because we’re not using an AMF service.

What I did instead was hack together a more elaborate and
depressing solution where I made an interface that I force any object calling
the delegate to implement.

twitteria_swiz/src/com/insideria/twitteria/delegates/TwitterResponder.as
#3-10 (formatted)

public interface TwitterResponder {
      function get username():String;
      function get password():String;
      function friendsTimelineResult(tweets:Array):void;
      function setStatusResult():void;
}

Then I can make sure I know how the instance of the delegate
should get the username and password, and that there’s a callback method for
getting the timeline and status results. I’m sure there’s an easier way, but
this occurred to me at the time. Some time in the future, I’d like to help Swiz
out of this mess and make it just as easy to arbitrarily work with delegates
that call any type of service. We’ll see if the time presents itself.

So now calling the delegate, which is the same old guy we’ve been
using from project to project, will call back to friendsTimelineResult on the controller when the
timeline is loaded, which sets the collection on the model.

twitteria_swiz/src/com/insideria/twitteria/controllers/MainViewController.as
#44-46

public function friendsTimelineResult(tweets:Array):void {
      model.currentTweets = new ArrayCollection(tweets);
}

Binding takes over from there and the new list is shown in MainView.

Setting Status

Just as before, pressing enter in the status text field will kick
off the chain of events to set status.

twitteria_swiz/src/com/insideria/twitteria/view/MainView.mxml
#15-18

private function setStatus():void {
      controller.setStatus(statusText.text); 
      statusText.clear();
}

This time we again elected to call up to the controller.

twitteria_swiz/src/com/insideria/twitteria/controllers/MainViewController.as
#26-29

public function setStatus(statusMessage:String):void {
      var delegate:TwitterDelegate = new TwitterDelegate(this);
      delegate.setStatus(statusMessage);
}

The controller calls out to the delegate, and the delegate
returns to say that the status is set, so we kick off a load timeline again to
get the latest tweets.

twitteria_swiz/src/com/insideria/twitteria/controllers/MainViewController.as
#48-51

public function setStatusResult():void {
      // reload tweets to get the newest

      loadTweets();
}

And that’s the Swiz version, folks!

Next Up

I’m supposed to be leaving the evaluations until the last
article, but I will say right away that Swiz certainly delivers on its promise
of cutting down boilerplate code. It’s a breeze to work with, and the only
tough spot is if you’re not using an AMF service.

Next time we’re going to look at our last framework, Mate, and
see how it takes advantage of MXML to make a simple, declarative Flex
framework.

Read more from
Tony Hillerson
.

FrameworkQuest Part 3 by Tony Hillerson
Find the original post here

FrameworkQuest 2008: Introduction
FrameworkQuest 2008 Part 2: Get Control with Cairngorm
FrameworkQuest 2008 Part 3: Agnostic Views with PureMVC
FrameworkQuest 2008 Part 4: IoC With Swiz
FrameworkQuest 2008 Part 5: Mate, the Pure MXML Framework
FrameworkQuest 2008 Part 6: The Exciting Conclusion

Last week we took a look at how to clean up our Twitter client by
using Cairngorm to separate the concerns according to the time honored MVC
architectural pattern. Now we’re going to see how it feels to work with PureMVC, an
ActionScript framework that wants to make it easier to do just that.

PureMVC was created by Cliff Hall, and is maintained in a few
different forms by a community of developers.

Notice that PureMVC is an ActionScript framework. More
specifically, there is an ActionScript 2 and two ActionScript 3 versions of
PureMVC, one regular and one multi-core, which can work with Flex with Modules
for instance. That’s one thing that PureMVC makes clear is that it has no
dependencies on the Flex Framework, which means that it’s flexible enough to
work with Flash projects as well as Flex. In fact PureMVC also has ports in the
works or already developed for Java, C#, ColdFusion, Ruby, and others, so it
tries to be a language independent take on an MVC framework.

Being framework independent means that unlike Cairngorm, PureMVC
doesn’t rely on Flex binding. Not only that, but PureMVC wants to make sure
that framework code doesn’t make it outside any of the classes that aren’t
clearly framework oriented. This certainly applies to view classes, so PureMVC
uses Flash events instead of a framework specific event type. This encourages
the development of views as black box components, which encourages a loosely
coupled architecture (which is also possible with Cairngorm) as well as a
framework independent view (which is not, strictly speaking, possible with
Cairngorm).

A little bit about the framework. PureMVC has a Controller, a Model, and a Facade, all singletons.  The Controller has an API for sending and
receiving Notifications,
which are event-like messages that any PureMVC object, except, by convention, Proxies, can
subscribe to. Proxies

never receive, they only send, Notifications.
The Model keeps
a set of named Proxy
objects, which are responsible for a particular type of data in the model. For
instance an application that has User objects would probably have a UserProxy that handled requests for
users and managed a collection of users. The Model and Controller are unseen, and only
accessed through the Facade.
The Facade has
an API for working with both the Model and Controller, sending Notifications,
looking up Proxies,
and so forth. Your application implements the Facade class either by implementing
the interface or extending a Facade

class that PureMVC provides. That brings up another point about PureMVC. Every
part of PureMVC implements an interface, which is also provided so that you
could replace any part of PureMVC with your own implementation if you wanted.

Let’s look at a flow of events in a PureMVC application.

When a user interacts with the view, a Flash event is dispatched
from the view. A Mediator
responsible for that view has already registered for interesting events and
when it receives this one, it may do view specific logic. Most likely, it will
also send a Notification

which any other PureMVC objects may elect to receive. Keep that point in mind –
that’s a very loosely coupled architecture. Any number of other Mediators or Commands can listen
for a certain notification and do whatever it is they do.

The Controller
is what gets called when a Notification

is sent, and it tells anyone interested in those types of Notifications that they have some new
mail. It’s also possible to register a Command to a certain type of Notification, and if one is found,
it’s instantiated and executed. This is typically the case in service calls.
The Command’s
job is then to get reference to a Proxy through the Facade and ask it to take some
appropriate action. The Proxy

can either interact directly with some service if necessary, or as is sometimes
done, a Cairngorm-style BusinessDelegate
can be invoked instead. PureMVC is flexible on this point, and some developers
find it desirable to have this service encapsulation for the same reasons as we
already described last time – it helps cushion the application from change.

Once the service returns to the Proxy directly or through a Delegate, it sends a Notification, which a
Mediator or
another Command

can receive. If the Mediator
listens for that Notification,
it’s because something needs to change on the view in response to the new state
of the data in the Proxy,
and the Mediator
is responsible for changing the view. It may do this by wiring data in a data
provider directly to a property on the Proxy.

So, a few differences from what we’ve seen with Cairngorm are:

1.    No
framework code in the views.

2.    No
singleton model, instead a set of Proxies

3.    No
Flex Binding, instead all views are encapsulated from the framework by Mediators.

Now that we’ve heard the dry details, let’s take a tour of our
app.

PureMVC TwitteRIA

As mentioned, most PureMVC actions go through the Facade we created, ApplicationFacade in
this case, and most access to the Facade is through helper methods on Mediator, Proxy, or Command. One time you’ll probably act
directly on the Facade

instance is at application startup, like we do here:

twitteria_puremvc/src/twitteria_puremvc.mxml #8, 16

creationComplete="facade.startup(this)"
...
private var facade:ApplicationFacade = 
                     ApplicationFacade.getInstance();

We get a reference to the instance of the Facade and call startup, passing the instance of the
view, when the application is complete. Let’s go through the startup phase and
see what happens there.

twitteria_puremvc/src/com/insideria/twitteria/ApplicationFacade.as
#23-30

override protected function initializeController():void {
     super.initializeController(); 
     registerCommand(STARTUP,        StartupCommand);
     registerCommand(LOG_IN,              LogInCommand);
     registerCommand(SET_STATUS,          SetStatusCommand);
     registerCommand(LOAD_TIMELINE,  LoadTimelineCommand);
}

First of all, when ApplicationFacade is first instantiated, initializeController

is called by the framework. Here we register commands to string constants.
Later on, when we send Notifications
created with these strings, the commands will be created and executed. For
instance, here’s the one for STARTUP.

twitteria_puremvc/src/com/insideria/twitteria/ApplicationFacade.as
#10


public static const STARTUP:String = "startup";

And now when we call startup we send a notification with the STARTUP string, which will cause a StartupCommand to be
executed. When we send the notification we also send along a reference to the
application.

twitteria_puremvc/src/com/insideria/twitteria/ApplicationFacade.as
#31-33

public function startup(app:twitteria_puremvc):void {
      sendNotification(STARTUP, app);
}

StartupCommand
is a MacroCommand,
which means it executes a set of sub-commands which we add in the framework
called initializeMacroCommand.

twitteria_puremvc/src/com/insideria/twitteria/controller/StartupCommand.as
#5-10

public class StartupCommand extends MacroCommand {
     override protected function initializeMacroCommand():void {
          addSubCommand(ModelPrepCommand);
          addSubCommand(ViewPrepCommand);
      }
}

The ModelPrepCommand
sets up the model:

twitteria_puremvc/src/com/insideria/twitteria/controller/ModelPrepCommand.as
#9-16


public class ModelPrepCommand extends SimpleCommand {
      override public function execute(note:INotification):void {
            facade.registerProxy(new TimelineProxy());
            facade.registerProxy(new StatusProxy());
            facade.registerProxy(new UserProxy());
       }
}

And the ViewPrepCommand
sets up the Mediators
that control the views.

twitteria_puremvc/src/com/insideria/twitteria/controller/ViewPrepCommand.as
#12-18

public class ViewPrepCommand extends SimpleCommand {
      override public function execute(note:INotification):void {
            var app:twitteria_puremvc = note.getBody() 
                 as twitteria_puremvc;
            facade.registerMediator(
                 new ApplicationMediator(app)
            );
            facade.registerMediator(
                 new LoginViewMediator(app.loginView)
            );
            facade.registerMediator(
                 new MainViewMediator(app.mainView)
            );
       }
}

Let’s analyze those two commands. First of all, note that they
both extend SimpleCommand.
Doing that gives them access through the ApplicationFacade singleton, which is
registered by the framework and provided to all framework classes. That lets
the commands register proxies and mediators easily. Registering those guys lets
anyone with access to the facade get a reference by name. We’ll look at that in
a bit.

One more thing to note is how we get the STARTUP notification passed to each
sub-command. Since we attached the reference to the application to the note, we
can grab that off the body and get a reference to the view items that each Mediator needs to
mediate.

Whew! That was a lot, and it all took place before the user even
sees the view. Now that  all that
is in place we can finally look at logging in.

Logging In

One other big difference in the root application from the Cairngorm
version is an omission on the ViewStack.

twitteria_puremvc/src/twitteria_puremvc.mxml #26

<mx:ViewStack id="mainViewStack" bottom="0" left="0" right="0" top="30">

There’s no binding to tell the stack which child to show. To see
where the ViewStack
is actually controlled, we look at the ApplicationMediator. When the Mediator is created in the ViewPrepCommand and
passed the application instance, the constructor keeps that reference.

twitteria_puremvc/src/com/insideria/twitteria/view/ApplicationMediator.as
#15-17

public function ApplicationMediator(viewComponent:twitteria_puremvc) {
     super(NAME, viewComponent);
}

Passing the app reference along with the NAME constant sets the viewComponent
property for this mediator and also registers with the Facade using NAME, which is an arbitrary string:

twitteria_puremvc/src/com/insideria/twitteria/view/ApplicationMediator.as
#10

public static const NAME:String = "ApplicationMediator";

Using that string lets anyone look the mediator up by that name.
It’s also usual to set up a little helper lookup to bring back the viewComponent as a
typed object of the type we know it to be:

twitteria_puremvc/src/com/insideria/twitteria/view/ApplicationMediator.as
#33-35

protected function get app():twitteria_puremvc {
     return viewComponent as twitteria_puremvc
}

When the ApplicationMediator
is registered, a framework method is called to set up the mediator.

twitteria_puremvc/src/com/insideria/twitteria/view/ApplicationMediator.as
#33-35


override public function listNotificationInterests():Array {
     return [
           ApplicationFacade.VIEW_TIMELINE
      ];
}

One method the framework calls is listNotificationInterests. This should return a list
of strings that the mediator is interested in receiving. Then, whenever any
notification with those types are sent through the facade, this mediator will
get notified. Notification happens when the framework calls handleNotification.

 

twitteria_puremvc/src/com/insideria/twitteria/view/ApplicationMediator.as
#25-31

override public function handleNotification(note:INotification):void {
     switch (note.getName()) {
            case ApplicationFacade.VIEW_TIMELINE:
                 app.mainViewStack.selectedIndex = MAIN_VIEW;
            break;
      }
}

This method gets called when any notification that the mediator
is interested in gets sent. The usual process is to switch on the notification
name and then do the right thing. 
In this case, when the VIEW_TIMELINE
note comes through, we want to switch the ViewStack index to the MAIN_VIEW constant,
which just like the Cairngorm implementation and just like the no-framework
implementation, points to the right index to show MainView. So that’s how the ApplicationMediator

does what it do, as they say. When does the VIEW_TIMELINE notification get sent?
Let’s look at the LoginView
to see.

twitteria_puremvc/src/com/insideria/twitteria/view/components/LoginView.mxml
#4-16

<mx:Metadata>
     [Event(name="login", type="flash.events.Event")]
</mx:Metadata>

<mx:Script>

<![CDATA[
     public static const LOGIN:String = 'login';

     public function login():void {
           dispatchEvent(new Event(LOGIN));
      }
]]>

</mx:Script>

The first thing you may notice is that we’re back to dispatching
a regular Flash event when enter is pressed on the password field:

twitteria_puremvc/src/com/insideria/twitteria/view/components/LoginView.mxml
#27


enter="login()"

Who’s listening? The LoginViewMediator, which as also set up in the ViewPrepCommand. When
the mediator is created, it adds itself as an event listener for this type.

twitteria_puremvc/src/com/insideria/twitteria/view/LoginViewMediator.mxml
#15-19

public function LoginViewMediator(viewComponent:LoginView) {
     super(NAME, viewComponent);
 
      view.addEventListener(LoginView.LOGIN, login);
}

So when the view dispatches that event, the mediator’s login
method will be called.

twitteria_puremvc/src/com/insideria/twitteria/view/LoginViewMediator.mxml
#15-19

private function login(event:Event):void {
      var credentials:Object = {
                 username:view.usernameText.text,
                 password:view.passwordText.text

       };
      sendNotification(ApplicationFacade.LOG_IN, credentials);
}

The login method gets a little ad-hoc object together and sends
it along with a notification. We could change that to be a typed object, but
for now a hash is good enough. The note name is in the LOG_IN variable on the facade, and if
you’ll remember, that was registered to the LoginCommand.

twitteria_puremvc/src/com/insideria/twitteria/controller/LoginCommand.as
#11-19

override public function execute(note:INotification):void {
      var userProxy:UserProxy = 
           facade.retrieveProxy(UserProxy.NAME) as UserProxy;
      var timelineProxy:TimelineProxy = 
           facade.retrieveProxy(TimelineProxy.NAME) as TimelineProxy;
      var credentials:Object = note.getBody();
 
      userProxy.username = credentials['username'];
      userProxy.password = credentials['password'];
      sendNotification(ApplicationFacade.LOAD_TIMELINE);
}

The UserProxy
simply stores the username and password; have a look at it if you want. With a
more complex login process it would get a little more complex too, but that’s
enough for here. Again, notice that the username/password hash is on the body
of the Notification.
At the end of the command, we send out another notification, signaling that
log-in is complete and it’s time to load the timeline.

Loading The Timeline

To load the timeline, we call on the TimelineProxy in the LoadTimelineCommand, which was
registered to the LOAD_TIMELINE
notification type.

twitteria_puremvc/src/com/insideria/twitteria/controller/LoadTimelineCommand.as
#10-13

override public function execute(note:INotification):void {
      var timelineProxy:TimelineProxy =
           facade.retrieveProxy(TimelineProxy.NAME) as TimelineProxy;
      timelineProxy.reload();
}

The reload
method goes like this:

twitteria_puremvc/src/com/insideria/twitteria/model/TimelineProxy.as
#22-25

public function reload():void {
      var delegate:TwitterDelegate = new TwitterDelegate(this);
      delegate.loadTimeline();
}

Notice that the TimelineProxy
implements IResponder,
and that I’ve chosen to use the Business Delegate pattern. Nothing from here to
the service changed from the Cairngorm implementation except that it’s a Proxy instead of a Command calling the
delegate. These choices aren’t mandated by PureMVC, but it’s flexible enough to
allow this way of doing things. I’m not sure I like the Proxy being an IResponder because that limits it to
only one set of result/fault methods and
only one call on the delegate. That could be changed to a more flexible event
listener approach, but for now I chose to keep things pretty similar to how
they were.

twitteria_puremvc/src/com/insideria/twitteria/model/TimelineProxy.as
#27-32

public function result(result:Object):void {
      var stati:Array = result as Array;
      currentTweets = new ArrayCollection(stati);
      sendNotification(ApplicationFacade.VIEW_TIMELINE);
      sendNotification(ApplicationFacade.TIMELINE_LOADED);
}

When the delegate returns to the result method, we fire off two
notifications: VIEW_TIMELINE
and TIMELINE_LOADED.
Why two? One lets the application know to change view states, and the other
lets the application know that there’s new data in the TimelineProxy. Those may happen
concurrently here, but they don’t always have to. If you remember back a bit, VIEW_TIMELINE was a
notification that the ApplicationMediator

was interested in. When this notification makes it there, that mediator
switches the index in the ViewStack
to show the MainView,
as you saw above. Who’s interested in the TIMELINE_LOADED notification? That
would be the MainViewMediator.

twitteria_puremvc/src/com/insideria/twitteria/view/MainViewMediator.mxml
#33-39

override public function handleNotification(note:INotification):void {
     switch (note.getName()) {
            case ApplicationFacade.TIMELINE_LOADED:
                 view.currentTweets = getTimelineProxy().currentTweets;
            break;
      }
}

When the MainViewMediator
gets the TIMELINE_LOADED
note, it sets the currentTweets
property to the TimelineProxy’s
currentTweets.
This is how the framework gets around binding the view to the model – the
mediator hooks the properties on a proxy directly to the view.

Now the view is on the MainView and the tweets are loaded into the list. It’s
time to set the status.

Setting Status

Just as the LoginView

dispatches a plain-old-flash-event when you hit enter, the MainView dispatches an event when the
status is set by pressing enter in the status field

twitteria_puremvc/src/com/insideria/twitteria/view/components/MainView.mxml
#4-23

<mx:Metadata>
     [Event(name="setStatus", type="flash.events.Event")]

</mx:Metadata>

<mx:Script>
<![CDATA[
     import mx.collections.ArrayCollection;

     public static const SET_STATUS:String = 'setStatus';

     [Bindable]
     public var currentTweets:ArrayCollection; // <TwitterStatus>

     private function setStatus():void {
           dispatchEvent(new Event(SET_STATUS));
           statusText.clear();
      }
]]>
</mx:Script>

The MainViewMediator
has an event listener, setStatus,
that handles that event.

twitteria_puremvc/src/com/insideria/twitteria/view/MainViewMediator.mxml
#41-43 (formatted)

private function setStatus(event:Event):void {
      sendNotification(
           ApplicationFacade.SET_STATUS,
           view.statusText.text
      );
}

The SET_STATUS
notification corresponds to the SetStatusCommand.

twitteria_puremvc/src/com/insideria/twitteria/controller/SetStatusCommand.as
#10-13 (formatted)

override public function execute(note:INotification):void {
      var statusProxy:StatusProxy =
           facade.retrieveProxy(StatusProxy.NAME) as StatusProxy;
      statusProxy.setStatus(note.getBody() as String);
}

The StatusProxy
calls out to the TwitterDelegate
just like the Cairngorm SetStatusCommand
used to.

twitteria_puremvc/src/com/insideria/twitteria/model/StatusProxy.as
#19-22

public function setStatus(statusText:String):void {
      var delegate:TwitterDelegate = new TwitterDelegate(this);
      delegate.setStatus(statusText);
}

And when the result comes back, it sends out just the LOAD_TIMELINE
notification, which as we saw above, kicks off the timeline load sequence.

twitteria_puremvc/src/com/insideria/twitteria/model/StatusProxy.as
#24-26


public function result(result:Object):void {
      sendNotification(ApplicationFacade.LOAD_TIMELINE);
}

Play around with the application, in dummy data mode and out.
Kick it around and see if you can think of anything to add. There are a lot of
moving parts to PureMVC, so think through the flows a bit again, just to make
sure you have an idea of what each piece does.

Next Up

Well folks, that’s PureMVC. Some key parts again are that nothing
from the framework enters the view components (except once, in the root
application), the model is broken up into many Proxies, views that need framework action
are acted upon by Mediators,
Commands
generally tell a Proxy
to do something, and communication between all the parts is done through Notifications.

It may strike you that you have to do a lot by hand to get
everything working together with PureMVC. If you’d like your framework to take
a little bit more initiative for you, then you might want to see what the Swiz
way of doing things looks like. That’s just what we’re going to do next time,
so watch this space!

Read more from
Tony Hillerson
.

Tags:

FrameworkQuest Part 2 by Tony Hillerson
Find the original post here

FrameworkQuest 2008: Introduction
FrameworkQuest 2008 Part 2: Get Control with Cairngorm
FrameworkQuest 2008 Part 3: Agnostic Views with PureMVC
FrameworkQuest 2008 Part 4: IoC With Swiz
FrameworkQuest 2008 Part 5: Mate, the Pure MXML Framework
FrameworkQuest 2008 Part 6: The Exciting Conclusion

Carebear? Carhorn? What?

Cairngorm is the Flex Framework with the odd name that’s been around almost since the beginning of Flex. It was created by a company called iteration::two, which went on to become Adobe Consulting’s European practice around the same time Adobe acquired Macromedia. These guys had been using Flex very early on, and were some of the first to talk about how important it was to building business applications. They even wrote the first commercially available Flex book, which helped to lend Cairngorm a lot of credibility when they released it soon after.

So what’s a Cairngorm? The Cairngorms are a mountain range in Scotland and Cairn Gorm is one of the famous peaks in that range. It’s 4000 feet above sea level, which isn’t impressive on paper to a Colorado-an like me (we have 25 peaks over 14,000 feet, and 56 over 4000m, so nyah-nyah), but then again, we have a continent underneath us to prop things up a bit. I’d love to see the Cairngorms one day and I’m sure the highland beauty, if not the mass quantities of Scotch Whisky, would make a suitable impression.

So how do you pronounce it? Most people say “CAREn-gorm”, and some say “CARn-gorm” (for American English values of “care” and “car”). I have no idea, but I think the “car” version may be closer to the Scotch pronunciation.

If you’d like to learn more about Cairngorm, the documentation is here.

Now, back to Flex land, let’s see where we left off.

Reviewing our Mess

In the last episode of our series on Frameworks we looked at an AIR application created using Flex, but used no Flex framework. Here are a list of problems we hope to solve with a framework.

  1. 1. Poor Organization
  2. 2. Unstructured Application State
  3. 3. Bloated Views

MVC to the Rescue

Many of you have heard of the concept of the Model/View/Controller architectural pattern. When we apply this pattern to an application, the code is separated into three general concerns – the Model, the View, and the Controller.

The Model is responsible for holding the state of the application, which means any information that the application could display, any information that the application needs to use to contact services, and any information about a particular session with a user, like where they are in the application.

The View is responsible for displaying the data in the model and informing the rest of the application about user interaction, such as the click of a button.

There are a few rules that MVC applies to the model and the view. One is that the model should not know about the view. That means that however the data gets from the model to the view, the model can’t be the one putting it there. Conversely, the view shouldn’t act directly on the model to change its state. Another rule is that the view shouldn’t know about the controller. It doesn’t have a reference to any part of the controller, so it can’t change anything about the controller directly.

That leaves The Controller to somehow respond to user interaction notifications from the view and inform the model appropriately, possibly changing the state of the model. Then through some mechanism that makes sense, the view is updated to reflect the new state of the model.

MVC was created to help keep business logic and view logic separate so that, theoretically, changes in the one don’t require changes in the other. The principles of MVC are going to show up in all the frameworks we discuss, so keep them in mind.

Now let’s look at how Cairngorm does things.

Cairngorm: Dramatis Personae

Cairngorm is described by Adobe Consulting as a microframework, or a set of patterns available to developers to assist in building an application. Here’s a normal flow of operations and the Cairngorm classes that are exercised.

When the user takes some sort of action on the view, such as clicking a button, the view dispatches a CairngormEvent. This event informs the FrontController, which instantiates a Command. The command executes the business logic, and the event is responsible for passing data to the command about the user interaction.

The command can either take some action on the Model, or instantiate and act on a Business Delegate. The Business Delegate, or delegate for short, wraps the code required for a service call, so it acts like the service API to the rest of the application. This is important because when the service changes, the changes to the application can be minimized and ideally only the delegate needs to change. The delegate calls the service and then depending on the kind of service involved makes sure that the command is informed when the service call has returned. Then the command changes the state of the model, if necessary, and the model, through Flex’s binding, updates the view.

That was a whirlwind tour, but if we look at some code I think it will become a little clearer.

TwitteRIA on Cairngorm

First we’ll look at changes to the top-level application. The Script-block has changed to this:

twitteria_cairngorm/src/twitteria_cairngorm.mxml #6-13

<mx:Script>
<![CDATA[
     import com.insideria.twitteria.model.TwitteRIAModel;

     [Bindable]
     private var model:TwitteRIAModel = TwitteRIAModel.getInstance();
]]>

</mx:Script>

Now, all we do is get an instance to the model. The model instance is bindable so that the view can bind to properties on the model. I say the model because Cairngorm only has one. The code in the model goes as far as possible in ActionScript 3 to make sure that nothing can instantiate the model except the model’s class. If you haven’t seen a Singleton implementation in AS3, here our Model as an example. First, there’s a private class variable to hold the singleton instance:

twitteria_cairngorm/src/com/insideria/twitteria/model/TwitteRIAModel.as #10

private static var instance:TwitteRIAModel;

Then, since we can’t have private constructors in AS3, the constructor doesn’t allow any other class to call new TwitteRIAModel() unless it passes an instance of the Private class:

twitteria_cairngorm/src/com/insideria/twitteria/model/TwitteRIAModel.as #27-31 (formatted)

public function TwitteRIAModel(access:Private) {
      if (access == null) {
            throw new 
                 CairngormError(
                       CairngormMessageCodes.SINGLETON_EXCEPTION,
                       "XCLModelLocator"
                 );
       }
}

which is defined on line 45, outside the package, making it virtually invisible outside of this file.

twitteria_cairngorm/src/com/insideria/twitteria/model/TwitteRIAModel.as #45

class Private {}

And finally the getInstance method returns the instance, creating it if it hasn’t already been created.

twitteria_cairngorm/src/com/insideria/twitteria/model/TwitteRIAModel.as #33-38

public static function getInstance():TwitteRIAModel {
      if (instance == null) {
            instance = new TwitteRIAModel(new Private());
       }
      return instance;
}

So much for Singletons. We’ll have more to say about them later. Back to the Application. Now that we have the model to hold state for the application, we can point the ViewStack at the model.

twitteria_cairngorm/src/twitteria_cairngorm.mxml #23-26 (formatted)

<mx:ViewStack selectedIndex="{model.mainViewIndex}">
     <view:LoginView id="loginView" />

     <view:MainView id="mainView" />
</mx:ViewStack>

Also note that the LoginView and MainView here no longer share the username and password between them, nor does the LoginView inform the Application of the login event. We’ll get to how those changed in a moment. For now, there’s one last important line on the Application:

twitteria_cairngorm/src/twitteria_cairngorm.mxml #15

<controller:TwitteRIAController id="controller" />

The Cairngorm FrontController needs to be instantiated early in the application’s lifecycle, and that’s generally done by defining it in MXML right in the root application. Another thing that’s usually instantiated alongside the controller is the ServiceLocator, which is generally a file that defines any services the application accesses to keep them all in the same place. Since our application doesn’t use the normal HTTPService or RemoteObject you usually see in a Cairngorm application, we don’t use the ServiceLocator.

The Controller, as mentioned above, is what takes care of capturing dispatched CairngormEvents and instantiating and executing the corresponding commands. You never actually interact directly with the controller in code, but you do wire up events to commands there, as shown here:

twitteria_cairngorm/src/com/insideria/twitteria/controller/TwitteRIAController.as #13-17 (formatted)

private function initialize():void {
      addCommand(
           LogInEvent.LogIn_Event, LogInCommand);
      addCommand(
           LoadTimelineEvent.LoadTimeline_Event, LoadTimelineCommand);
      addCommand(
           SetStatusEvent.SetStatus_Event, SetStatusCommand);
}

Now whenever, for instance, a LogInEvent is dispatched, the FrontController instantiates a LogInCommand and executes it.

Logging In

Now lets look at logging in. Where before we just had the LoginView’s username and password bound to the MainView, we’re going to take a more scalable approach this time. What we really want is to keep the username and password around so that we can access them from anywhere we need them. That’s what the model is for. Now look at the LoginView’s login method, which before emitted an event:

twitteria_cairngorm/src/com/insideria/twitteria/view/LoginView.mxml #7-9

public function login():void {
      new LogInEvent(usernameText.text, passwordText.text).dispatch();
}

Now the method dispatches a LogInEvent, which holds a username and a password. When it’s dispatched with its own dispatch method, the LogInCommand is instantiated and executed, with the event passed along.

twitteria_cairngorm/src/com/insideria/twitteria/command/LoginCommand.as #13-19

public function execute(event:CairngormEvent):void {
      var evt:LogInEvent = event as LogInEvent;
      model.username = evt.username;
      model.password = evt.password;
      model.mainViewIndex = TwitteRIAModel.MAIN_VIEW;
}

After setting the username and password properties on the model to the values on the event, the command changes the mainViewIndex property to the MAIN_VIEW constant on the model. If you remember, the ViewStack in the application had its index bound to model.mainViewIndex.

twitteria_cairngorm/src/twitteria_cairngorm.mxml #23 (formatted)

<mx:ViewStack selectedIndex="{model.mainViewIndex}">

The constants on the model help give some idea what they are used for:

twitteria_cairngorm/src/com/insideria/twitteria/model/TwitteRIAModel.as #16-19

public static const LOGIN_VIEW:int  = 0;
public static const MAIN_VIEW:int   = 1;
[Bindable]

public var mainViewIndex:int        = LOGIN_VIEW;

So when the LoginCommand changes the mainViewIndex to MAIN_VIEW, the ViewStack changes to show MainView.

There are two examples of how the Cairngorm model holds both application state and view state. You also see can see an example of how a Cairngorm command is tasked with a specific responsibility, in this case setting credentials and making sure the view state matches the logged in view – basically taking care of what needs to be done to log in, just like the command name leads you to believe. In this way the commands and FrontController together make up the Controller part of MVC for Cairngorm.

I like that about Cairngorm. If you want to know how the app works and where that work is done, you just need to look through the command directory and see a list of descriptive verbs that tell you what takes place and what class does it.

Loading the Timeline

Now let’s look at how we load the timeline. Again, when the MainView’s creation is complete, the init method is called:

twitteria_cairngorm/src/com/insideria/twitteria/view/MainView.mxml #14-16

private function init():void {
      new LoadTimelineEvent().dispatch();
}

Instead of doing any work inside the MainView, like we did before, now we dispatch a CairngormEvent that loads the timeline. That event corresponds to the LoadTimelineCommand.

twitteria_cairngorm/src/com/insideria/twitteria/command/LoadTimelineCommand.as #16-20

public function execute(event:CairngormEvent):void {
      var evt:LoadTimelineEvent = event as LoadTimelineEvent;
      var delegate:TwitterDelegate = new TwitterDelegate(this);
      delegate.loadTimeline();
}

The execute method doesn’t do that much, in fact it delegates responsibility to the TwitterDelegate. If you remember, delegates are the guys that wrap the service API and cushion the rest of the app from changes to the services. All we need to know here is that the delegate will load the timeline, and we ask it to do so.

I should make a note here that I’m breaking a bit with Cairngorm convention. Generally Cairngorm has you define one delegate for each event/command pair. That gets a little chunky for my taste, and instead I usually define one delegate for every resource I’m accessing on the service side. For instance if I had a user service with an API for creating, updating, deleting, getting a user, and getting all users, I’d have one delegate for users which would have methods to execute each of those operations. Again, this is not Cairngorm convention, this is my way of doing things. It’s not like I’m hurting Cairngorm, though, and it shows that the framework is flexible enough to meet your needs, or in this case, a matter of taste.

Let’s look at the delegate. In the constructor you can see more characteristic Cairngorm code:

twitteria_cairngorm/src/com/insideria/twitteria/business/TwitterDelegate.as #20-21

public function TwitterDelegate(responder:IResponder) {
      this.responder = responder;

Notice how the argument to the constructor isn’t a Command, but an IResponder. That interface is part of the mx.rpc package that ships with Flex, and it describes two methods – result and fault. Cairngorm makes use of this interface for commands that are asynchronous, which means that they “fire and forget” calls off to the service, and expect to be called back when the service returns from the call. If you’ve been around Flex and Flash for any length of time, you know that just about everything follows this pattern of callbacks. In this case Cairngorm designed delegates to take an object that has a method, result, to callback when a service returns with a result, and fault, a method to call back if something goes wrong. It doesn’t care how that happens in the delegate or service, and the command implementing IResponder doesn’t need to know either. It just needs to know if the call worked or didn’t, and then act accordingly. The responder is set into a private property for later use.

twitteria_cairngorm/src/com/insideria/twitteria/business/TwitterDelegate.as #23-25 (formatted)

twitterService = new Twitter();
twitterService.setAuthenticationCredentials(
     model.username, model.password
);
twitterService.addEventListener(
     TwitterEvent.ON_FRIENDS_TIMELINE_RESULT,
     friendsTimelineLoaded
);

Next, the delegate creates an instance of Twitter, sets the credentials to the username and password the LoginCommand stored on the model, and registers some callbacks on the twitter service. Most times you’ll see RemoteObjects or HTTPServices inside delegates and things look a little different than you see here. RemoteObjects call AMF services, and they know how to deal with responders. Luckily though, the delegate is flexible enough to deal with our situation where we need to instantiate and set up the service right here.

Once the callbacks for each type of Twitter service call, a call of that type should call back to the method in the delegate. When we ask for the timeline, callbacks should go to the friendsTimelineLoaded method:

twitteria_cairngorm/src/com/insideria/twitteria/business/TwitterDelegate.as #49-51

private function friendsTimelineLoaded(te:TwitterEvent):void {
      responder.result(te.data as Array);
}

And that method just calls the result method on the responder with the timeline data it gets from Twitter. This is clean, because now the command doesn’t need to know anything about the Twitter class or the TwitterEvent that comes back, it just needs to know about an array of tweets that comes to the result method.

By the way there’s no fault thrown from Twitterscript, so the fault method isn’t going to ever be called, but you can imagine how it would be if there were.

Now, when the command calls loadTimeline, the delegate does this:

twitteria_cairngorm/src/com/insideria/twitteria/business/TwitterDelegate.as #29-38 (formatted)

public function loadTimeline():void {
      if (useDummyData) {
            var te:TwitterEvent = new TwitterEvent(
                 TwitterEvent.ON_FRIENDS_TIMELINE_RESULT
            );
            te.data = getDummyData();
            friendsTimelineLoaded(te);
       } else {
            twitterService.loadFriendsTimeline(model.username);
       }
}

And there’s our old friend, the dummy data. Although this still isn’t what I’d call a good way of choosing which data to load, real or fake, at least it’s all sectioned off into the delegate and no one else needs to know how it’s done. That’s called encapsulation, and just like when the delegate wraps the service, it cushions the rest of the application from change.

When LoadTimelineCommand finally gets result called, it creates a new ArrayCollection to wrap the array of tweets and places it on the model.

twitteria_cairngorm/src/com/insideria/twitteria/command/LoadTimelineCommand.as #22-25

public function result(result:Object):void {
      var stati:Array = result as Array;
      model.currentTweets = new ArrayCollection(stati);
}

That’s a very Cairngorm like sequence, there. Command calls delegate, delegate calls service, service returns to delegate (or sometimes straight to command), and then on to result, which changes something on the model. Then Flex binding takes over and modifies the view.

twitteria_cairngorm/src/com/insideria/twitteria/view/MainView.mxml #32

dataProvider="{model.currentTweets}"

Since the list in the main view is bound to the model’s currentTweets property, it will reset itself to show the new list. Slick!

Setting Status

There’s not a lot to show for setting status, since everything works pretty much the same. In fact, that’s something you can get used to with Cairngorm – if you want to know what happens because of a user interaction, find the command that gets executed and you’ll probably learn everything you need to know about what goes on. If not, you can follow back to the delegate, but the command does the bulk of the heavy lifting on the client side. Here’s SetStatusCommand’s execute:

public function execute(event:CairngormEvent):void {
      var evt:SetStatusEvent = event as SetStatusEvent;
      var delegate:TwitterDelegate = new TwitterDelegate(this);
      delegate.setStatus(evt.statusText);
}

and result:

public function result(result:Object):void {
      new LoadTimelineEvent().dispatch();
}

Notice how we have to dispatch the LoadTimelineEvent from the result? That’s one thing that some other frameworks try to work around. This command’s responsibility is telling Twitter what sweet new lolcat picture we just posted or trojan-linking in a Rick Astley video, not loading the timeline, but now we’ve tied this command up with loading the timeline. We could have had the MainView dispatch the next event if we somehow alerted the view to the fact that the status had been set, but that’s a little iffy too. In any case, the next thing that needs to happen when the status is set is to reload the timeline, so we do it here, and that’s all we need to do.

Keep that in mind for when we move on to other frameworks, because we’re out of time for today. You’ve seen how we’ve used Cairngorm’s CairngormEvents, the command pattern, delegates, and a singleton model to clean things up considerably from where we left things off last time. Next time we’ll see another framework that aims to clean some of the framework code out of the view, and rebuild our application using PureMVC.

Read more from
Tony Hillerson

I have moved to a different location

check out my new home Flexout

calendar

November 2017
M T W T F S S
« May    
 12345
6789101112
13141516171819
20212223242526
27282930  

Blog Stat

  • 83,759 Hop's so far!!!

follow me

Error: Twitter did not respond. Please wait a few minutes and refresh this page.

Archives

Linkedin Blogger Twitter Youtube Orkut

latest flickr photos

top rated