Aug 7, 2011

GraniteDS Tutorial: Intro to The Tide Client Framework

 

Introduction to Tide Client Framework

    The Tide Client Framework is a very simple and lightweight framework that can greatly simplify developing your Flex/GraniteDS application. Tide allows you to declaratively or programmatically auto-wire your software components (UI widgets, controllers, etc) together, making data sharing and event routing a much simpler task.

    While Tide has many features and capabilities, including tight integration with server side capabilities, this tutorial will briefly introduce the Tide Context, and how it enables data injection and simplified event routing.  

 

The Tide Context

    The Tide Context is the manager for everything that is to be handled and auto-wired by the framework, and there is only one per Application (or one per Seam conversation). Once a component is registered with the Tide Context singleton, that component is registered to work with injection and Tide events.  What that means is Tide will automatically inject shared data and correctly route events without requiring the application developer to write their own mechanism for sharing information or explicitly registering event listeners.

Tide Context - Intro

Figure 1 – Example of several components and views registered with the Tide Context

Injection

    Injection is a means of sharing data between components registered with the Tide Context. Once an object is added to the context, that object can be used by any other component registered with the Tide context by simply injecting the object with the [In] metadata. Figure 2 below shows an example of when a control is added to the context, Tide automatically scans the control for injections, and autowires the references to the correct objects.

Tide Context - Shared Object

Figure 2 – Example of a View and Controller Sharing an Object

 

[Name("MyView")]
[Bindable]
public class MyView
{
   [In]
   public var mySharedObject:MySharedObject;
   …
}
[Name("MyViewController")]
[Bindable]
public class MyViewController
{
   [In]
   public var mySharedObject:MySharedObject;
   …
}

Figure 3 - Example Source of View and Controller Sharing an Object via Injection

Tide Events

    Tide events are a simplification on the already existing Flex event framework. However, rather than requiring a tight coupling between components and forcing entities to know about each other in order to register for events, Tide will broadcast Tide Events (any event extending AbstractTideEvent) to any listeners registered within the context that have registered with the [Observer] meta data for that type of event.

    Consider a simple example of 1 sender and 2 listeners as shown in Figures 4 below. If the listeners and senders are all in the same context, events are automatically routed to the proper listeners without any additional work or calls to “addEventListener()”.

[Name("MyEventSender")]
[Bindable]
Public class MyEventSender
{
   …
   //Send MyEvent to any listeners that reside in the tide context.
   public function sendSomeEvent() : void
   {
      var e:MyEvent = new MyEvent();
      dispatchEvent(e);
   }
}
[Name("MyEventListener")]
[Bindable]
Public class MyEventListener
{
   …
   //Method will be called automatically whenever anything in the same context
   // dispatches a MyEvent.
   [Observer]
   Public function OnMyEvent(e:MyEvent) : void
   {
      //Do something neat
   }
}
[Name("MyEventListener2")]
[Bindable]
Public class MyEventListener2
{
   …
   //Method will be called automatically whenever anything in the same context
   // dispatches a MyEvent.
   [Observer]
   Public function onSomethingHappenedThatICareAbout(e:MyEvent) : void
   {
      //Do something else that is neat
   }
}

Figure 4 - Tide Event Senders and Listeners Source

 

Tide Context - Events

Figure 5 - Example of 3 components registered with context, 1 that sends a simplified tide event, and 2 that will listen for that event

 

    Tide events work like magic, but the implementation is quite simple.  When a component is registered with the context, Tide scans the class for [Observer] tags and registers listeners using normal “addEventListeners” means.  Then when a Tide event is dispatched, Tide finds all observer methods that match the event type registered with the context, and calls those methods directly.

Tide Context - EventsFlow

Figure 6 - Details of how a simplified Tide event is relayed to listeners

How to Add Views/Controllers to the Context

     Components can be added to the Tide context and therefore registered with the Tide client framework via three of different methods (let me know if there are more). 

  1. Observed events
  2. Injection/Outjection
  3. Setting as a property on the context directly

Observed Events

    When a component class has been registered with Tide via Seam.getInstance().addComponents(classes), Tide will scan the registered class looking for “[Observer]” annotated event handler methods.  If the specified event is ever dispatched, Tide will find all classes that observe the event, instantiating instances of the handler class if an instance doesn’t already exist in the Tide context.  In the example below, when the tide context (or when any component already managed by the tide context) dispatches the “MyEvent” event, Tide will construct a new instance of MyControl if an instance is not already managed by the context.

 
//Register the control class with Tide.
Seam.getInstance().addComponents(MyControl);

//Dispatch a MyEvent, which will instantiate any registered controls that observe
//this event type if control doesn’t already exist in context
tideContext.dispatchEvent(new MyEvent());
[Bindable]
[Name(“MyControl”)]
public class MyControl
{
    [Observer]
    public function myEventHandler(event:MyEvent)
    {  
        //Do something fantastic
    }
}

Figure 7 – Instantiating and Adding a control to the context via registered observer

Injection / Outjection

    If a component is managed by Tide and has an injected/outjected reference to another object, that object will also be managed by Tide and the context.   So if an instance of MyControl in figure 8 were added to the tide context using any of the means mentioned, the injected MyView would also be created and and added to the context. 

Note:  If an instance of MyView named “myViewUI” already existed in the context, Tide would simply auto-wire this reference to point the instance already managed by Tide.

 
[Bindable]
[Name(“MyControl”)]
public class MyControl
{
   [In]
   public var myViewUI:MyView;
}

Figure 8 – Adding a view to the context via injection

Setting as a property on the context directly

    The last option to add a component to the Tide context is to set it as a property directly on the context.  E.g. “tideContext.myViewUI = new MyView();”.  Actually no matter how you try to add a component to the Tide context, it will ultimately result in a call to “setProperty(name:*, value:*)” on the context.  Setting a property on the context will trigger Tide to scan the object injections/outjections, observer methods, etc. so that it can be auto-wired correctly with other components in the context.

   Tide Context - Scan and Add

Figure 9 - Setting component as a property of the context

 

Conclusion

    The Tide client framework is a pretty powerful framework that can greatly simplify development.  Data Injection and simplified events makes the collaboration and sharing of data between components a snap.  All in all, it’s a pretty good micro-architecture to work with.

    In my next article I will cover Tide “Subcontexts”, an undocumented feature of the Tide Client Framework that gives developers even more power and flexibility. 

4 comments:

j4 said...

Very Good Article. Thanks.

j4 said...

Very Good Article. Thanks.

Hassen KOUKI said...

Thanks for this nice article.

Bosbos.

Anonymous said...

Very nice article.