Communication Between Classes in AS2 Using EventDispatcher

Now I know that AS3 is all the rage now and I really do love the changes made which most definitely make my life easier coding, however, I remember a major breakthrough I had with writing classes in AS2 and still use AS2 due to the lack of computers in the UK hospitals which either still run off windows NT and so cannot upgrade to Adobe Flash Player 8/9 or are not permitted downloads or installations full stop. So publishing to Flash Player 7 regularly occurs and thus AS2 still represents in my world and I am sure many others. So, lets go back a wee bit and tackle a pain in the rear period I had in comprehending the logic behind parsing data between classes and my saving grace…. EventDispatcher.

Stefan really came to my rescue here when I first started coming to grips with OOP and classes in actionscript and pretty much over a week, every problem I had he just gave me the same reply, just dispatch an event. So I read the help files, searched the net and it was like a light on a dimmer switch slowly brightening, man I do not know why I never got to grips with it sooner but once I did life got a heck of a lot easier developing and the whole class concept rocketed. So for all you developers who are starting out with classes in AS2 and and want to gain the same leverage as myself then read on…

I have included links to source files which I will walk through, source consists of 3 classes and an FLA. I have used the concept of an XML playlist for a custom built MP3 player which is pulled into and process by the classes then an instance of a class object is dynamically attached to the stage in the FLA. From there all the information is freely available for you to use in your own custom built player (video or mp3), and by the way I do not run through here on how to construct a Flash MP3 player. This is a nice introduction into how to write a class, import XML and process the data finally dispatching the XML data to a class which is attached to the stage.

First up, PlayListLoader.as. The sole function of this class is to bring in the xml, attach all the relevant node information to a custom class object, push the object data to an array and dispatch it, job done, end of… First useful bit of information is scope in classes, primary cause of 90% of my headaches. You need to be aware that when you use a callback function (which we will, the onLoad method) issues can arise using the this keyword, does it refer to the class object or the XML object. To overcome this we create a pointer to the local class file within the onLoad handler. For further clarification please read: scope in classes.

Soooo, we have the xml loaded, and if you look in the onLoad handler we have called the classes init() method which simply loads the buildPlayList() method. The buildPlayList method creates a new ‘items_array’ array, the perfect structure for storing loops of mixed data type information, we then do a simple loop through all the item nodes.

Now we bring in the PlayListObject.as class which as you can see is a list of variables and an empty constructor. You could, as we loop through the xml nodes, attach each piece of node data to a plain ol’ Object, however, a class is simply an object anyway and if we create a custom class object for our information we can ensure a more efficient datatyping process in this application. So we target the item node and loop through them all, create a new instance of our custom class object and name it ‘item_obj’ and then create new properties on the item_obj then assign each relevant element of the item node e.g. the property filename on the item_obj stores the item filename i.e. track1.mp3. Just to stop and reflect, we are still within a loop here, so when we get to the stage of putting the item_obj into the items_array Array we are putting in the first item node data, if there is another item node in our xml then we go through the whole process again, hence the name ‘loop’! yeh ok stated the obvious but anywho, we get that object into the array by using the Array method ’push’.

Lets jump out of the loop next and call the displayPlayList method, this is where I saw the light. In this method we call dispatchEvent which is a method of broadcasting events and is used by all components that extend UIObject. The dispatchEvent() method is defined in the mx.events.EventDispatcher class and therefore needs to be imported and also initialised, so look to the top of the class and you will see the:

1
import mx.events.EventDispatcher;

We must declare the following methods of the EventDispatcher class as members of our class:

1
2
3
public var dispatchEvent:Function;
public var addEventListener:Function;
public var removeEventListener:Function;

And in the constructor:

1
2
// Assign this class as the event dispatcher
      EventDispatcher.initialize(this);

In the initialisation we defined ‘this’ our class as the event dispatcher. These are the key concepts in a simple straight forward example for dispatching events from a class, google searches pull up various in depth articles on the EventDispatcher classes.

The dispatchEvent method takes a parameter ‘target’ which is a reference to who is dispatching the event, be it a class, button, movieclip etc. Next up is the ‘type’ property which we call “complete” as we call it when our xml is loaded and parsed to our array. Another example or a ‘type’ property is the “click” event used by buttons. We can then add whatever properties we want, yup, we could pass all sorts of information, an array, string, number, build it up how ya like, thats the beauty of the dispatchEvent method we use, we simply need to pass one property….wait for it…items_array! PlayListLoader, see ya…

In comes PlayList.as, our class which listens out for the dispatched event. To do that we add and remove EventListener public variables just below the class definition then within the init() method we need to create a new instance of the PlayListLoader class named ‘playlist_data’. We have imported the PlayListLoader class at the top of our script and now we have created an instance of the class so we can listen out for an event from that class via the instance we created once we attach an event listener.

1
2
// Add event listener for out for the dispatching of the playlist
      playlist_data.addEventListener("complete", Delegate.create(this, completeHandler));

Urm, Delegate who? Well read here and then just use it when you wanna run a method on receipt of your dispatched event, easy, honest, look at that line of script, ‘playlist_data’ - our class instance dispatching the event, addEventListener - add a listener to the instance, “complete” - the type parameter we named in the PlayListLoader class dispatchEvent method and finally the Delegate.create(this, completeHandler) - the first parameter is scopeObject, a reference to an object to run the function which for us is ‘this’, our class, completeHandler is the method we want to run when we receive the event. Whew…. Overload, so sit, chill, digest, check out this then come back and lets move on.

Lets summarise for a second, we have our PlayListLoader class which sorts through our xml, assigns data to our instance of the PlayListObject class and pushes it all to an Array, dispatched from the PlayListLoader class to whoever is listening. Now, PlayList.as happens to be listening, and when it receives our event (“complete”) it is in the form of an object, an event object, makes sense? So when we call the completeHandler method using Delegate.create, we actually pass it the event object. So what is in the event object? You ain’t gonna believe this but its our ‘items_array’, here it is in all it glory, attached to an object swinging from side to side after its swift transfer from one class to another.

So lets see how we pass it to the completeHandler method. Its an object, its getting passed but as yet we can not reference it, so we need to give it a name, lets be clear and name it eventObject and datatype it for what it is, an Object. This all gets done within the called method brackets as seen below:

1
private function completeHandler(eventObject:Object):Void

We can know access the data in this method my first typing eventObject then the name of the parameter we are passing in the dispatchEvent which we call ‘items’ (an array) then loop through the items picking off the properties required for example:

1
eventObject.items[1].filename

would pull the first filename property in the item array which is ‘track1.mp3’. All I do in the PlayList class is output the xml information parsed using trace statements to demonstrate that they have been indeed parsed over from one class to another, you now have all this data to do what you want with. This keeps all your functionality separate from the class which simply pulls in all the xml keeping thing nicely organised i.e. one class pulls in info, other class processes info, another class displays info etc.

Just to finish off, some may be wondering how we then get these classes on the stage of your .fla. I have attached playlist.fla which demonstrates how we do this. The easiest way to think about this is to remember that classes are essentially objects and in this particular example we are going to hypothetically create an MP3 player which is a visual object and so would be contained within a MovieClip. So we get going by creating a movieclip and naming it PlayList, the same as the class we want to attach to our stage. We then click Export For ActionScript and assign the class name PlayList into the AS 2.0 Class text field. This basically grabs our class Object and pops it into this movieclip so we have a visual representation to either drag and drop onto our stage and give an instance name, or alternatively as I have done, attach to the Stage dynamically using code as below:

1
2
3
4
5
6
7
8
9
// Import the PlayList class
import PlayList;

// Define the object playListLoader_mc
var playListLoader_mc:PlayList;

/* Attach an instance of the PlayList object (class) to the stage and give it an
 * instance name playListLoader_mc  */
this.playListLoader_mc = this.attachMovie("PlayList", "playListLoader_mc", this.getNextHighestDepth());

As we have done throughout the example with classes we want to utilise, we import them, reference the, through an instance name variable, here we use ‘playListLoader_mc’ and datatype it to its class ‘PlayList’ and use the attach movie method to attach it to the stage. You will now find when you test and run the application you will find the trace statements appear in the Output window.

I hope that this fairly long winded walk though helps someone out there with communicating between classes and that I have given you an example which is of relevance for projects of potential development (MP3 players are a funky option to start building).

And finally if this was of any use please drop me a comment and I will endeavor being a sad man and sit in on a Saturday night writing like this again :) (my excuse is my wife has left me to run the London marathon, good luck babe)!!!!

source_files

Comments