Section 13.4. Listenable Shared Objects

13.4. Listenable Shared Objects

The SimplePeopleList component provides a view of the data in a userList shared object by listing the shared object's data properties. Other components may also need to use the userList shared object and be notified when the onSync( ) method is called. In one respect, the SimplePeopleList treats the userList shared object as it treats its List component; it simply adds itself as an event listener for onSync events. Remote shared objects must be modified in order to dispatch events or add and remove event listeners. When an object or component in this chapter needs to connect to a shared object, it uses the SharedObjectFactory class listed in Example 13-2 instead of the SharedObject class. The SharedObjectFactory class retrieves a remote shared object and then adds methods and properties to it so that one or more objects or components can add themselves to the shared object as event listeners. It uses the EventDispatcher class provided as part of the v2 UI component framework to perform part of the customization of each shared object. The code in Example 13-2 must be placed in a file named SharedObjectFactory.as . Read through the heavily commented example if you are interested in how the SharedObjectFactory converts a remote shared object into a v2-style event dispatcher.

Example 13-2. The SharedObjectFactory class
 class SharedObjectFactory extends Object {   /*   getRemote( )   calls   SharedObject.getRemote( )   to get a shared object reference    * and then uses the   mx.events.EventDispatcher   object to make the shared    * object into a v2 component-style event broadcaster. Also, an   isConnected   * flag is maintained to implement an   onFirstSync   event and to keep track of     * the shared object's connection state. Finally, two methods have been added     * to dynamically add and remove remote methods to and from the shared object.    */   static function getRemote (name, uri, persistence) {     // Get the remote shared object.     var so = SharedObject.getRemote.apply(SharedObject, arguments);     // If it exists and has not been modified to be a broadcaster...     if (so && !so._onFirstSync) {       // Make it an event broadcaster.       mx.events.EventDispatcher.initialize(so);       // Define an   _onFirstSync( )   method that can be assigned to   onSync   // whenever an attempt is made to connect the shared object.       so._onFirstSync = function (list:Array) {         this.isConnected = true;         this.dispatchEvent({type:"onFirstSync", target: this, list:list});         this.onSync = this._onSync;         this.onSync(list);       };       /* Define an   _onSync( )   method to assign to   onSync   after the first        *   onSync( )   has been called. Note the   event.list   property contains        * the list normally passed to   onSync( )   .       */       so._onSync = function (list:Array) {          this.dispatchEvent({type:"onSync", target: this, list:list});       };       // Keep a reference to the   SharedObject.connect( )   method.       so._connect = so.connect;       // Replace   connect( )   with a method that modifies   onSync   and   isConnected   // before calling the original   connect( )   method.       so.connect = function (nc:NetConnection) {         this.onSync = this._onFirstSync;         this.isConnected = false;         this._connect(nc);       };       // Keep a reference to the original   SharedObject.close( )   method.       so._close = so.close;       // Modify the   close( )   method to set the   isConnected   flag before       // actually closing the shared object.       so.close = function ( ) {         this.isConnected = false;         this._close( );       };       /* Dynamically attach a remote method to the shared object. Note        * the method simply dispatches an event to any interested listeners        * and includes the   arguments   object so listeners can deal with the        * remote call themselves. Listeners must use   addEventListener( )   on the        * shared object to receive remote method call notifications.        *   addRemoteMethod( )   and   removeRemoteMethod( )   are discussed later.        */       so.addRemoteMethod = function (methodName) {         so[methodName] = function ( ) {           this.dispatchEvent({type:methodName, target: this, args:arguments});         };       };       // Delete the remote method if it is no longer needed.       so.removeRemoteMethod = function (methodName) {         delete so[methodName];       };     }     return so;   } } 

If you use the SharedObjectFactory class in place of the SharedObject class to get a remote shared object, you should never have to customize another shared object again. All you have to do is get the shared object with SharedObjectFactory.getRemote( ) and decide what events a listener needs to receive. You can add remote methods to the shared object using addRemoteMethod( ) and receive remote method events by having a listener listen for remote calls by name.

Example 13-3 is a short demonstration of how the SharedObjectFactory class can be used. It demonstrates adding event listeners for both onFirstSync and onSync events and defining and listening for a remote method (arbitrarily named rmiCheck( ) in this example). The TestSOListener class can be used to create a simple soListener object for test purposes. The onFirstSync event was created as an extra event beyond onSync to provide notice only when the shared object first connects. The TestSOListener class listing is extensively commented and is provided in Example 13-3 so you can see how to listen for each type of event and extract information from each event object.

Example 13-3. The TestSOListener class is designed to show how to use the SharedObjectFactory class
 class TestSOListener { /* TestSOListener is a test/demonstration class that shows  * how a class can work with a shared object returned by  * the   SharedObjectFactory.getRemote( )   method.  */ function TestSOListener ( ) {}   /*   onFirstSync( )   is called once after the shared object first connects.    *   ev.target   is a reference to the shared object.    *   ev.list   is the list of information objects passed into the    * shared object's   onSync( )   method the first time it was called.    */   function onFirstSync (ev) {     var list = ev.list;     var so = ev.target;     // Write out some information about the list.     trace("onFirstSync> list length: " + list.length);     // Write out the properties of the shared object.     for (var p in so.data) {       trace(p + ": " + so.data[p]);     }     // Test remote method invocation (RMI) by sending      // an   rmiCheck   message with two parameters.     so.send("rmiCheck", "First Parameter", "Second Parameter");     // Test the   onSync( )   method by adding data to the shared object.     so.data.hello = "Greetings!";   }   /*   onSync( )   is called immediately after the   onFirstSync   event and    * is passed the same list   onFirstSync( )   was passed. Afterward, it is    * called whenever   onSync( )   is called on the shared object.    *   ev.target   is a reference to the shared object.    *   ev.list   is the list of information objects passed into the    * shared object's   onSync( )   method.    */   function onSync (ev) {     var list = ev.list;     var so = ev.target;     trace("onSync> list length: " + list.length);     for (var i in list) {       var info = list[i];       for (var p in info) {         trace(p + ": " + info[p]);       }     }   }   /*   rmiCheck( )   is called whenever the   rmiCheck( )   method is invoked    * on the shared object.    *   ev.target   holds a reference to the shared object and    *   ev.args   holds a reference to the arguments passed by the    * remote method call.    */   function rmiCheck (ev) {     var args = ev.args;     var so   = ev.target;     // Show that we have been called.     trace("rmiCheck> args.length: " + ev.args.length);     // Trace out the arguments passed to this method.     for (var i in args) {       trace("arg " + i + ": " + args[i]);     }     // If you don't want to look through the arguments, call     // another method this way.     this.rmiCheckHandler.apply(this, ev.args);   }   //   rmiCheckHandler( )   is called from   rmiCheck( )   using   apply( )   // and shows that normal parameter passing can be used.   function rmiCheckHandler (first, second) {     trace("rmiCheckHandler>");     trace("   first: " + first);     trace("  second: " + second);   } } 

The simplest way to try out the class is to create an instance of it on the main timeline, connect to the server, get a test shared object, and set up soListener as a listener for onFirstSync and onSync events. We also set up a remote method named rmiCheck( ) on the shared object and set up the soListener to receive an event whenever rmiCheck( ) is called:

 soListener = new TestSOListener(  ); nc = new NetConnection(  ); nc.onStatus = function (info) {   trace("nc.status> " + info.code);   if (info.code == "NetConnection.Connect.Success") {     so = SharedObjectFactory.getRemote("Test", nc.uri);     so.addEventListener("onSync", soListener);     so.addEventListener("onFirstSync", soListener);     so.addRemoteMethod("rmiCheck");     so.addEventListener("rmiCheck", soListener);     so.connect(nc);   } }; nc.connect("rtmp:/empty"); 

Output from this test script shows that onSync( ) is always called immediately after onFirstSync( ) is called and is passed the same information list. This is a convenience that provides flexibility in how the two events are handled. For example, one listener may listen for only the onSync event and not the onFirstSync event while another may listen for only the onFirstSync event or for both.

 nc.status> NetConnection.Connect.Success onFirstSync> list length: 1 onSync> list length: 1 code: clear rmiCheck> args.length: 2 arg 1: Second Parameter arg 0: First Parameter rmiCheckHandler>    first: First Parameter   second: Second Parameter onSync> list length: 1 code: success name: hello 

The remainder of this chapter and Chapter 15 make extensive use of the SharedObjectFactory class to create remote shared objects that don't require any further customization.



Programming Flash Communication Server
Programming Flash Communication Server
ISBN: 0596005040
EAN: 2147483647
Year: 2003
Pages: 203

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net