Juten Tach,
today i was juggling with Events quite a bit. By the way, isn’t it odd, that EventDispatcher does not reveal its listeners? At least to its subclasses? Or at the very least have some kind of “removeAllListeners()” method (like Robert Penner already noticed)?
Anyway, i was thinking: Events in Flash are all over the place nowadays. You use them in DisplayObjects, in your classes and also Flex has them everywhere. The good thing about them is, they could make threads needless. I sometimes see some developers shout for threads in Flash and i want to shout back: “Are you kidding?” To whomever Java developer i speak to, they all say, handling threads is a mess. I have no practical experience myself, but i know the basics of threads in Java. Events come to the rescue. They are easy to understand and to handle. It would only take the ability to dispatch an Event, which only fires AFTER the return of the method, that wanted to fire it. This way, we would be able to avoid weird issues like: “ClassA instantiates ClassB, adds itself as a listener to ClassB, but ClassB already fires an event in its constructor” (yeah, i know, not the best example, but i hope you get the point). And all the multicore and threading stuff could be managed in the background.
I think, Events should become first-class citizens of the ActionScript language at long last. It would allow for some cool new ways of expressing things. Imagine this:
package { import flash.events.Event; import com.sample.CoolEvent; import org.sample.OtherEvent; public class Example dispatches CoolEvent,OtherEvent { private listener myListener:EventFromCoolOtherClass.STARTED; public function Example() { init(); } private function init():void { someOtherClass = new CoolOtherClass(); myListener = someOtherClass >> someHandlerMethod; // blah, doing stuff dispatch async new CoolEvent(CoolEvent.COMPLETE); } private function someHandlerMethod(evt:Event):void { myListener = null; } // ... private function someOtherFunction():void { // blah, doing more stuff dispatch new OtherEvent(OtherEvent.STOPPED); } } }
These are just some thoughts, that came out of my head within the last hours. For example, it would be nice to be able to define officially, which events a class dispatches. And if you define it in the class header, you have to implement the dispatching, otherwise you’d get a compile time error (we could need this for errors as well, by the way, but different story). Then the ‘listener’ property. It works a bit like a pipe. Yo specify the listener and give it the Event type, you’re interested in. And in code you wire the dispatcher together with your handler method. Simply unwire by setting the listener to null.
Dispatching an event is almost like today, but you have the async option, which let’s the init method return, before the event is fired, which releases the stack (only works, if dispatch is the last statement in the method body, of course).
Probably i have forgotten some details, which might make these things not work the way i imagine, but anyway: Events should finally become a part of the ActionScript DNA.
Juten Tach,
today i stumbled upon a weird bug in the mxmlc compiler. I filed a bug, which turned out to be a duplicate of an earlier report here.
It basically goes like this:
Say, you have a swf file, which wants to spread its classes over multiple frames (if you read my previous post, it might sound familiar). So, to keep things simple, let’s say, you want to have two frames, each holding one class, let’s call them FirstFrameClass and SecondFrameClass. And additionally this swf file uses an external library, means, a .swc that should NOT be compiled into our .swf. Let’s assume, in that .swf there is one class, we call it LibraryClass.
Now the weirdness starts. If FirstFrameClass references LibraryClass, LibraryClass gets compiled into our resulting swf, although we specified the library to be an external one (using external-library-path in the compiler configuration). If instead SecondFrameClass references LibraryClass and not FirstFrameClass, LibraryClass gets NOT compiled into our resulting .swf file, just the way we want it.
In the end, the issue is, only if you reference a class from an external library in a class, which sits on the last frame of your own .swf file, the external-library option works, otherwise it is simply ignored.
In the bug report it says, the issue will be resolved for the upcoming Flex Hero release. I tested with the current build, but the issue is not resolved yet (which makes sense, because the bug entry in Adobes bug tracker is not set to Resolved yet).
If you find this as weird as i do, please vote for the bug.
Juten Tach,
say, you have a swf file, that contains some functionality, that you want to use in a main application. Roughly, this functionality will consist of an interface (by which in this case i mean a bunch of classes, which make the functionality public to the client classes) and the internal implementation (a bunch of classes behind the interface, which do the real work).
In a modular world, it would be nice to have the implementation be separate from the interface. In fact, so separate, that you could exchange it at runtime, if you wish to do so. So to be concrete, it would be nice, if the interface classes would be loaded into the main ApplicationDomain, so that everybody can use them and that the implementation classes would be loaded into a child ApplicationDomain, so that i could exchange them at runtime, if i want to.
No problem, you say, make two swf files. One with the interfaces, one with the implementation. Bahh, i answer, because i don’t want to spread my module over two swf files.
The solution is: Frames! The idea goes like this:
- You create your interface classes (again, these are not necessarily just interfaces, might also be some classes). You will also want to create some kind of factory or facade, which will create the real instances and decouple the implementation from your interface. Within the facade or factory, you have to use getDefinitionByName(…) to reference the implementation, because you don’t want your implementation to get compiled into this frame. The facade will be the only place, where the implementation is indirectly referenced. The interface should have no references to the implementation (why would it anyway?!).
- You create your implementation. The implementation can have references to the interface, of course. Probably mostly in the form of inheritance, or interface implementation and of course composition.
- Now you build your swf, either using the -frame compiler option or the Frame Metatag. Make sure, that the facade/factory and the interface compiles into the first frame and the implementation compiles into the second frame. It would make sense, that the Facade/Factory is actually the main class for your swf, so it has to extend MovieClip. This main class has to make sure, that it stops at the first frame, once the swf is loaded. Very important!
- Now, in your main application, you need to implement some loading logic, that actually does the magic.
- You load the swf from above into the main ApplicationDomain by using ApplicationDomain.currentDomain. Since the swf stops at the first frame, only the classes from the first frame are now available to your application. These are: The factory/facade and the interface classes.
- Now you load the same swf a second time, but not using Loader.load(…), but instead using Loader.loadBytes(…) in conjunction with Loader.contentLoaderInfo.bytes. And this time, you load it into a child ApplicationDomain, using new ApplicationDomain(ApplicationDomain.currentDomain). This way, the whole thing goes faster, and you don’t have to actually make a new request over the net.
- And now, you tell this newly loaded swf to go to second frame, which makes the implementation classes available (Since it started in the first frame, the facade/factory and interface classes are also loaded again, but they will be ignored this time, because they already exist in the main ApplicationDomain). But now the implementation classes are only available in the child ApplicationDomain.
- Make sure, that you never go to the second frame in the first loaded Loader (you might want to nullify it, so you don’t accidentally do it). Because then, the whole benefit would be lost, because the implementation then would also exist in the main ApplicationDomain.
That’s it. This way, you can now unload the implementation and load a new one, if necessary. The facade/factory and the interfaces will stay. Which brings up a little catch: If you want to exchange the implementation successfully, you have to make sure, that class paths are always the same in the different implementations, otherwise, the facade wouldn’t work, of course. You could circumvent this, if you put the facade into the implementation frame as well and let some generic mechanics in the main application do the fetching.
Testing this, by the way, i found that jumping to a frame three (with gotoAndStop(3)) always introduces the classes in a frame two as well. Which is a pity, because otherwise you would have been very flexible in deciding, which classes you want to put in which ApplicationDomain.
Juten Tach,
i am currently porting some code from Java to ActionScript. And of course, doing that makes some differences between these languages directly visible. One thing for example is: getter/setter methods. I love the ActionScript getter/setter approach. I think, it is pretty well-thought-out. The good thing about it is, that they look like a property. Which has the nice benefit, that in ActionScript you can always start with a public property first and change it to getter/setter, if you want to do something during assignment or return, or if you simply want to prohibit assignment. This is completely different to Java, where the rule of thumb is to always use getter and setter methods in the first place. Which makes absolute sense there, because getters have a different appearance to a client than properties.
Now, since getters and setters are so different in ActionScript compared to Java, i think, Interfaces in ActionScript should also look different, at least for some details. The job of an interface is to describe how to use an object. It should not describe, how the object implements functionality. Thus in Java only methods are allowed to be defined in an interface (and static properties for some reason). Which makes sense, because for accessing properties, in Java you would certainly use getter and setter methods.
ActionScript is different though. And that’s why i think, in ActionScript it should be allowed to define properties in an interface and let an implementing class decide, if it implements these properties using a real public property or getter and setters. Only if you want implementing classes to implement a read-only property, you would add the “get” keyword to the definition in the interface. So, an interface, that would want to define a property that is read-write enabled, could look like this:
interface Something { var myPublicField:String; }
And a class implementing that interface could start with implementing that field with a simple class variable, OR by using setters and getters, like so:
class Someone implements Something { var _myPublicField:String; public function get myPublicField():String { return _myPublicField; } public function set myPublicField(value:String):void { if(everythingIsOK) _myPublicField = value; } ... }
And an interface wanting to restrict the field to read-only could add the “get” keyword:
interface SomethingReadOnly { var get myPublicField:String; }
Note, that i am not so focused on the concrete notation here. Probably there could be better ways to notate these things. The point is, currently the only thing you can do in an interface is to define getter and setter functions, which automatically means, you have to implement them, even if a public property would be sufficient for a start. So the interface in fact defines the way to implement the field, which it shouldn’t.
Juten Tach,
if you’re looking at the upper right corner of this blog, you will notice, i am not working for Interone anymore. Nope, i am now working as a freelancer. After six and a half years it was time to start a new chapter. And that means, i’m more involved in coding again than before, which is good, because that was the plan.
And being here, i already got stuck with some specialties of good old Flash again.
I am currently investigating on how close one can implement the OSGi specification in AS3. I don’t want to get into too much detail about OSGi here, only so much: We’re talking about modules, that have dependencies to other modules. My thinking is, if ModuleA has a dependency to ModuleB, then ModuleB doesn’t necessarily have to know something about ModuleA, right? In fact, it would be nice, if ModuleA would be hidden from ModuleB, so that it cannot accidentally break something.
So i thought, hey, ApplicationDomains. If ModuleA is loaded into a child ApplicationDomain of ModuleB, then ModuleA has access to everything from ModuleB, but ModuleA is still hidden from ModuleB and cannot accidentally break something, because classes from ModuleA are not made directly accessible to ModuleB. Great.
Or not so. It is not uncommon, that one Module has more than just one dependency. So now let’s assume, ModuleA is not only dependent on ModuleB but also on ModuleC.
Yes, do it, think …
It doesn’t work, right? Since ModuleA is already loaded into a child ApplicationDomain of ModuleB, that same instance of ModuleA cannot also be loaded into a child ApplicationDomain of ModuleC, because an ApplicationDomain can only have one parent.
That alone means, one will never be able to implement the OSGi specification closely, because the only solution would be, to load everything into the main ApplicationDomain, which means, that you cannot completely unload (or uninstall, as OSGi puts it) a module again, because the class definitions would always stay (different to child ApplicationDomains, where the class definitions go, if you unload the respective swf).
Too bad.
[Update]: A colleague just pointed me to another issue: If you have a scenario like this:
Main ApplicationDomain -> child ApplicationDomain -> grandchild ApplicationDomain
[Update 2]: Oh man, sometimes a little bit more investigation would be advisable. Accessing a grand parent ApplicationDomain DOES work, it only needs code free of bugs … ![]()
Thanks senocular!
