Implementing IEventDispatcher

english mobile

Recently, I had to have a class that took arguments in its constructor and also was able to dispatch events. Rather than trying to extend EventDispatcher and worry about separating the arguments the rest of the class needed from the ones EventDispatcher needed, I decided to implement IEventDispatcher. Problem was, I hadn't done this in a while, and I couldn't remember the right way to do this and had no idea what project had an example of it. So, I went searching on the web and refreshed my memory that you need to include an EventDispatcher instance in your class and route your IEventDispatcher methods through that object.

I created some boilerplate code that I can just cut and paste to add IEventDispatcher support to a class, and I share it with you now.



//--------------Support for IEventDispatcher--------------//


private var _ed:EventDispatcher;

public
function addEventListener(type:String, listener:Function,
useCapture:Boolean=false, priority:int=0,
useWeakReference:Boolean=false):void
{
_ed.addEventListener(type,
listener, useCapture, priority, useWeakReference);
}
public function
removeEventListener(type:String, listener:Function,
useCapture:Boolean=false):void
{
_ed.removeEventListener(type, listener,
useCapture);
}
public function
dispatchEvent(event:Event):Boolean
{
return
_ed.dispatchEvent(event);
}
public function
hasEventListener(type:String):Boolean
{
return
_ed.hasEventListener(type);
}
public function
willTrigger(type:String):Boolean
{
return _ed.willTrigger(type);
}



Enjoy!

Updated 12/15/08:
Note that you'll need to put an instance of EventDispatcher in _ed in the constructor of the class that's implementing IEventDispatcher:

_ed=new EventDispatcher(this);

Updated 12/21/08:
Josh McDonald posted code that shows how to implement IEventDispatcher with boilerplate that doesn't require adding a line to the constructor.

More thoughts on Remoting

english mobile

As I mentioned in my last post, I've been working with AMF for the first time this week. I'd read about using AsyncTokens to be able to determine which call to a service resulted in which result, so from the very beginning I'd intended to use this. The problem I had was that when I looked at the docs for RemoteObject, I couldn't find anything that actually returns an AsyncToken. So at first I figured I couldn't do it.

But here's the thing. All of my commands to access the RemoteObject use static properties and methods, which essentially means that for each service there's only one RemoteObject that gets used from any object in the application that needs to call that service. These different parts of the application didn't know about each other, and I didn't want them to. Nor did I want to make these commands refuse any new calls before the old one was finished. So I had to make this AsyncToken thing work, or completely change the architecture of how I was calling AMF.

Finally, I found the documentation for mx.rpc.remoting.Operation (don't ask me how). It turns out that a remoting Operation is the method on the service that you're calling. When you call a RemoteObject operation, you're invoking the Operation Class's send method, so it seems that creating an AsyncToken from a RemoteObject call is as simple as myToken:AsyncToken=myRemoteObject.myService(whateverParameters). I'm not sure exactly how you're supposed to figure that out unless you happen to luck into the right information like I did, since there's no direct link between the language reference on RemoteObjects and that on Operation, and it's only referred to in passing in a parentetical expression in the RemoteObject "how to" type documentation.

One of my command classes needed to be able to accept a result and fault function from the instance that was calling the service, so I then needed to find a way to set a Responder on the token. The first thing I tried was simply to push a new Responder onto the token's responders Array. Let me save you a little time and tell you in advance this doesn't work. Instead, you need to use the AsyncToken's addResponder() method.

Thoughts on remoting

english mobile

The past week or so, I've been doing something that's new to me--retrieving objects using AMFPHP and integrating them with Flex. In the meantime, I've found that there are some things that are hard to find out about the whole process, so I thought I'd make a note of them here.

First, all the examples I could find easily used NetConnection. The code on these was so similar that I think there was one basic example that has been modified slightly by several different people and posted. I had better luck using RemoteObject, and I finally found an example of this.

The next thing I ran up against is that you have to use a RemoteClass alias on your Flex class that defines the object that is receiving the data. The docs are a bit misleading in that it sounds like you only need to use this if you are sending to a remote service and the service is Java based. However, if you read a bit further (I didn't at first), you can see that this applies pretty much to any AMF mapping. If you are sending data only from the service to Flex and you're not sending data back from Flex to the service, the only thing that matters about this alias is that it must match the $_explicitType variable in the object on the PHP side.

I also discovered a few things on my own. My classes extended EventDispatcher, and at first they didn't deserialize properly. We speculated that the fact that the class wasn't just a subclass of Object might have been the problem, but it turns out that extending EventDispatcher doesn't break serialization. My classes also had their own methods and some additional properties. We speculated that these were causing the problem, but it seems that serialization ignores these things. I think that if I were sending data back to PHP through the RemoteObject, I'd need to mark those properties as transient.

I think the real reason the serialization wasn't working was the last thing I discovered, which is that you have to have a dummy variable typed as your custom class in the same class as the RemoteObject that you're using to retrieve the values. This makes sure that the class definition gets compiled into the class where it can be used.

Oh, and one more thing... To a PHP programmer who's not familiar with ActionScript, a setter looks like something he can't serialize to. So it's probably better to just write up a description of the properties you're expecting to have set than sending the PHP person your actionscript class as is.