Okay, we’ve all used the <mx:RemoteObject> tag before, but now that we are following some good design principles and using a model view controller setup, we want to get rid of that tag and put the remote object logic into it’s own class.
When you decide to go ahead and start creating your own remote object classes in AS3, your’re going to have to keep in mind not only good design principles, but also encapsulation. This post is going to show you how to create an AS3 class that encapsulates the logic for connecting to a server side data service (In this one I am going to use ColdFusion, but you can easily substitute your own Ruby or Php based service). We are going to assume that you have a good understanding of Object Oriented AS3, as well as the AS3 event model.
When we create a remote service class over here we like to extend the EventDispatcher class. (The EventDispatcher class is the most primitive non-visual class in AS3 that can get and recieve events. If this was a visual component I would have used the Sprite class.) This way, the remote object class can send and recieve events in a relatively easy manner. The class signature ends up looking something like this:
public class MyRemoteEvent extends EventDispatcher{
}
public function MyRemoteEvent(target:IEventDispatcher=null)
{
super(target);
}
Now, at this point you can use a singleton design pattern to define the class, but I prefer to leave the singleton pattern to any intermediate functions that I would create to manage the events between the UI and the remote service.
Once we have decided on (if any) a design pattern, then we go on to actually build the class. For the purposes of this tutorial, I’m going to omit the package directive.
public class MyRemoteEvent(target:IEventDispatcher=null){
import mx.collections.ArrayCollection;
import mx.rpc.remoting.RemoteObject;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
private var _myConnection:RemoteObject;
private var _myArrayCollection:ArrayCollection;
super(target);
_myConnection = new RemoteObject;
_myConnection.destination = “ColdFusion”;
_myConnection.source = “Your.Service.Path”;
//create some event handlers
_myConnection.addEventListener(ResultEvent.RESULT, serviceSuccessHandler);
_myConnection.addEventListener(FaultEvent.FAULT, genericFaultHandler);
}
In the above constructor, we are simply setting up our remote object, and adding the event handlers to the same remote object. For example purposes I have put the ResultEvent.RESULT handler on the main object itself. This will trigger whenever you get a result event from the remote object. In a production version you are going to want to add the Result listener(s) only to the RemoteObject’s methods that you are planning on using. For Example if my remote object has a method called addCustomer, then my eventListener on the object _myConnection would look like: _myConnection.addCustomer.addEventListener(ResultEvent.RESULT, …blah, blah, blah.
Alot of the Flex documentation out there will show you that you can bind the resultObject of a remote procedure call directly to a visual component. In practice I have found that this is not the case, or even best practice. To make your remote classes more reusable, I find that it’s really important to cast the data returned from the rpc into either an array or arraycollection.
In the example above, lets imagine that our rpc returns an object with a name and a birthday, as an array object that flex will place into the result event. In the event handler function below we are going to take in the result event, and then create a loop that iterates over the result set, casting each row into an object. We will then push each object into an array, and then use the array as the source for a new ArrayCollection.
private function serviceSuccessHandler(event:ResultEvent):void{
//get the length of the result array – this is going to be different for each remote object.
//Init a new array to hold the result objects.
var length:int = event.result.length;
var tempArray:Array = [];
//Create the loop to iterate over the result set.
for(var i:int=0; i<length; i++){
//create a temp object
var tempObj:Object = {
name:event.result[i].name,
birthday:event.result[i].birthday
}
//push the temp object into the array
tempArray.push(tempObj);
}
//create the arraycollection
_myArrayCollection = new ArrayCollection(tempArray);
//dispatch a custom event to let the app know you’ve got the data….
dispatchEvent()…….
}
And there you have it. To finish off the operation, you can dispatch a custom event with the array collection inside, or create a get function to shuffle the operation off to another service. That’s about it for now, Happy Coding!